mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-04 11:49:02 +08:00
✅ test: add tests for OpenAIAPIClient reasoning effort parameter format
Co-authored-by: GeorgeDong32 <98630204+GeorgeDong32@users.noreply.github.com>
This commit is contained in:
parent
044eac0cf9
commit
de1e2a94bd
@ -0,0 +1,219 @@
|
||||
import type { Assistant, Model, Provider } from '@renderer/types'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { OpenAIAPIClient } from '../openai/OpenAIApiClient'
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('@renderer/config/models', () => ({
|
||||
isSupportedReasoningEffortOpenAIModel: vi.fn((model: Model) => {
|
||||
const modelId = model.id.toLowerCase()
|
||||
return (
|
||||
modelId.includes('gpt-5') ||
|
||||
(modelId.includes('o1') && !modelId.includes('o1-preview') && !modelId.includes('o1-mini')) ||
|
||||
modelId.includes('o3') ||
|
||||
modelId.includes('o4')
|
||||
)
|
||||
}),
|
||||
isSupportedReasoningEffortGrokModel: vi.fn((model: Model) => {
|
||||
return model.id.toLowerCase().includes('grok')
|
||||
}),
|
||||
isSupportedReasoningEffortPerplexityModel: vi.fn((model: Model) => {
|
||||
return model.id.toLowerCase().includes('sonar-deep-research')
|
||||
}),
|
||||
isSupportedReasoningEffortModel: vi.fn((model: Model) => {
|
||||
const modelId = model.id.toLowerCase()
|
||||
return (
|
||||
modelId.includes('gpt-5') ||
|
||||
modelId.includes('o1') ||
|
||||
modelId.includes('o3') ||
|
||||
modelId.includes('o4') ||
|
||||
modelId.includes('grok') ||
|
||||
modelId.includes('sonar-deep-research')
|
||||
)
|
||||
}),
|
||||
isReasoningModel: vi.fn(() => true),
|
||||
isOpenAIDeepResearchModel: vi.fn(() => false),
|
||||
isSupportedThinkingTokenZhipuModel: vi.fn(() => false),
|
||||
isDeepSeekHybridInferenceModel: vi.fn(() => false),
|
||||
isSupportedThinkingTokenGeminiModel: vi.fn(() => false),
|
||||
isSupportedThinkingTokenQwenModel: vi.fn(() => false),
|
||||
isSupportedThinkingTokenHunyuanModel: vi.fn(() => false),
|
||||
isSupportedThinkingTokenClaudeModel: vi.fn(() => false),
|
||||
isSupportedThinkingTokenDoubaoModel: vi.fn(() => false),
|
||||
isQwenReasoningModel: vi.fn(() => false),
|
||||
isGrokReasoningModel: vi.fn(() => false),
|
||||
isOpenAIReasoningModel: vi.fn(() => false),
|
||||
isSupportedThinkingTokenModel: vi.fn(() => false),
|
||||
isQwenAlwaysThinkModel: vi.fn(() => false),
|
||||
isDoubaoThinkingAutoModel: vi.fn(() => false),
|
||||
getThinkModelType: vi.fn(() => 'default'),
|
||||
GEMINI_FLASH_MODEL_REGEX: /gemini.*flash/i,
|
||||
MODEL_SUPPORTED_REASONING_EFFORT: {
|
||||
default: ['low', 'medium', 'high'],
|
||||
grok: ['low', 'high'],
|
||||
perplexity: ['low', 'medium', 'high'],
|
||||
gpt5: ['minimal', 'low', 'medium', 'high']
|
||||
},
|
||||
findTokenLimit: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@renderer/config/providers', () => ({
|
||||
isSupportEnableThinkingProvider: vi.fn(() => false)
|
||||
}))
|
||||
|
||||
vi.mock('@renderer/hooks/useSettings', () => ({
|
||||
getStoreSetting: vi.fn(() => ({
|
||||
summaryText: 'off'
|
||||
}))
|
||||
}))
|
||||
|
||||
vi.mock('@renderer/types', () => ({
|
||||
SystemProviderIds: {
|
||||
groq: 'groq',
|
||||
openrouter: 'openrouter',
|
||||
dashscope: 'dashscope',
|
||||
doubao: 'doubao',
|
||||
silicon: 'silicon',
|
||||
ppio: 'ppio',
|
||||
poe: 'poe'
|
||||
},
|
||||
EFFORT_RATIO: {
|
||||
minimal: 0.1,
|
||||
low: 0.3,
|
||||
medium: 0.5,
|
||||
high: 0.8,
|
||||
auto: 1
|
||||
}
|
||||
}))
|
||||
|
||||
describe('OpenAIAPIClient - Reasoning Effort', () => {
|
||||
let client: OpenAIAPIClient
|
||||
let provider: Provider
|
||||
let assistant: Assistant
|
||||
|
||||
beforeEach(() => {
|
||||
provider = {
|
||||
id: 'copilot',
|
||||
name: 'Github Copilot',
|
||||
type: 'openai',
|
||||
apiKey: 'test-key',
|
||||
apiHost: 'https://api.githubcopilot.com/',
|
||||
models: []
|
||||
}
|
||||
|
||||
client = new OpenAIAPIClient(provider)
|
||||
|
||||
assistant = {
|
||||
id: 'test-assistant',
|
||||
name: 'Test Assistant',
|
||||
emoji: '🤖',
|
||||
prompt: 'You are a helpful assistant',
|
||||
topics: [],
|
||||
messages: [],
|
||||
type: 'assistant',
|
||||
regularPhrases: [],
|
||||
settings: {
|
||||
reasoning_effort: 'medium'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
describe('GPT-5 models through GitHub Copilot', () => {
|
||||
it('should return reasoning object format for gpt-5-mini', () => {
|
||||
const model: Model = {
|
||||
id: 'gpt-5-mini',
|
||||
name: 'GPT-5 Mini',
|
||||
provider: 'copilot',
|
||||
group: 'openai'
|
||||
}
|
||||
|
||||
const result = client.getReasoningEffort(assistant, model)
|
||||
|
||||
// Should use base class implementation which returns { reasoning: { effort, summary } }
|
||||
expect(result).toHaveProperty('reasoning')
|
||||
expect(result.reasoning).toHaveProperty('effort', 'medium')
|
||||
expect(result.reasoning).toHaveProperty('summary')
|
||||
expect(result).not.toHaveProperty('reasoning_effort')
|
||||
})
|
||||
|
||||
it('should return reasoning object format for o1-2024-12-17', () => {
|
||||
const model: Model = {
|
||||
id: 'o1-2024-12-17',
|
||||
name: 'O1',
|
||||
provider: 'copilot',
|
||||
group: 'openai'
|
||||
}
|
||||
|
||||
const result = client.getReasoningEffort(assistant, model)
|
||||
|
||||
expect(result).toHaveProperty('reasoning')
|
||||
expect(result.reasoning).toHaveProperty('effort', 'medium')
|
||||
expect(result).not.toHaveProperty('reasoning_effort')
|
||||
})
|
||||
|
||||
it('should return reasoning object format for o3-mini', () => {
|
||||
const model: Model = {
|
||||
id: 'o3-mini',
|
||||
name: 'O3 Mini',
|
||||
provider: 'copilot',
|
||||
group: 'openai'
|
||||
}
|
||||
|
||||
const result = client.getReasoningEffort(assistant, model)
|
||||
|
||||
expect(result).toHaveProperty('reasoning')
|
||||
expect(result.reasoning).toHaveProperty('effort', 'medium')
|
||||
expect(result).not.toHaveProperty('reasoning_effort')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Non-OpenAI reasoning models', () => {
|
||||
it('should return reasoning_effort format for Grok models', () => {
|
||||
const model: Model = {
|
||||
id: 'grok-3-mini',
|
||||
name: 'Grok 3 Mini',
|
||||
provider: 'grok',
|
||||
group: 'xai'
|
||||
}
|
||||
|
||||
const result = client.getReasoningEffort(assistant, model)
|
||||
|
||||
// Should use reasoning_effort for non-OpenAI models
|
||||
expect(result).toHaveProperty('reasoning_effort', 'medium')
|
||||
expect(result).not.toHaveProperty('reasoning')
|
||||
})
|
||||
|
||||
it('should return reasoning_effort format for Perplexity models', () => {
|
||||
const model: Model = {
|
||||
id: 'sonar-deep-research',
|
||||
name: 'Sonar Deep Research',
|
||||
provider: 'perplexity',
|
||||
group: 'perplexity'
|
||||
}
|
||||
|
||||
const result = client.getReasoningEffort(assistant, model)
|
||||
|
||||
expect(result).toHaveProperty('reasoning_effort', 'medium')
|
||||
expect(result).not.toHaveProperty('reasoning')
|
||||
})
|
||||
})
|
||||
|
||||
describe('When reasoning_effort is not set', () => {
|
||||
beforeEach(() => {
|
||||
assistant.settings = {}
|
||||
})
|
||||
|
||||
it('should return empty object for GPT-5 models', () => {
|
||||
const model: Model = {
|
||||
id: 'gpt-5-mini',
|
||||
name: 'GPT-5 Mini',
|
||||
provider: 'copilot',
|
||||
group: 'openai'
|
||||
}
|
||||
|
||||
const result = client.getReasoningEffort(assistant, model)
|
||||
|
||||
expect(result).toEqual({})
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
Reference in New Issue
Block a user