mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
fix: 优化droid默认启用推理的问题
This commit is contained in:
@@ -10,16 +10,6 @@ const logger = require('../utils/logger')
|
|||||||
|
|
||||||
const SYSTEM_PROMPT = 'You are Droid, an AI software engineering agent built by Factory.'
|
const SYSTEM_PROMPT = 'You are Droid, an AI software engineering agent built by Factory.'
|
||||||
|
|
||||||
const MODEL_REASONING_CONFIG = {
|
|
||||||
'claude-opus-4-1-20250805': 'off',
|
|
||||||
'claude-sonnet-4-20250514': 'medium',
|
|
||||||
'claude-sonnet-4-5-20250929': 'high',
|
|
||||||
'gpt-5-2025-08-07': 'high',
|
|
||||||
'gpt-5-codex': 'off'
|
|
||||||
}
|
|
||||||
|
|
||||||
const VALID_REASONING_LEVELS = new Set(['low', 'medium', 'high'])
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Droid API 转发服务
|
* Droid API 转发服务
|
||||||
*/
|
*/
|
||||||
@@ -35,16 +25,7 @@ class DroidRelayService {
|
|||||||
|
|
||||||
this.userAgent = 'factory-cli/0.19.4'
|
this.userAgent = 'factory-cli/0.19.4'
|
||||||
this.systemPrompt = SYSTEM_PROMPT
|
this.systemPrompt = SYSTEM_PROMPT
|
||||||
this.modelReasoningMap = new Map()
|
|
||||||
this.API_KEY_STICKY_PREFIX = 'droid_api_key'
|
this.API_KEY_STICKY_PREFIX = 'droid_api_key'
|
||||||
|
|
||||||
Object.entries(MODEL_REASONING_CONFIG).forEach(([modelId, level]) => {
|
|
||||||
if (!modelId) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const normalized = typeof level === 'string' ? level.toLowerCase() : ''
|
|
||||||
this.modelReasoningMap.set(modelId, normalized)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_normalizeEndpointType(endpointType) {
|
_normalizeEndpointType(endpointType) {
|
||||||
@@ -82,7 +63,6 @@ class DroidRelayService {
|
|||||||
logger.info(`🔄 将请求模型从 ${originalModel} 映射为 ${mappedModel}`)
|
logger.info(`🔄 将请求模型从 ${originalModel} 映射为 ${mappedModel}`)
|
||||||
}
|
}
|
||||||
normalizedBody.model = mappedModel
|
normalizedBody.model = mappedModel
|
||||||
normalizedBody.__forceDisableThinking = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -901,9 +881,7 @@ class DroidRelayService {
|
|||||||
headers['x-api-key'] = 'placeholder'
|
headers['x-api-key'] = 'placeholder'
|
||||||
headers['x-api-provider'] = 'anthropic'
|
headers['x-api-provider'] = 'anthropic'
|
||||||
|
|
||||||
// 处理 anthropic-beta 头
|
if (this._isThinkingRequested(requestBody)) {
|
||||||
const reasoningLevel = this._getReasoningLevel(requestBody)
|
|
||||||
if (reasoningLevel) {
|
|
||||||
headers['anthropic-beta'] = 'interleaved-thinking-2025-05-14'
|
headers['anthropic-beta'] = 'interleaved-thinking-2025-05-14'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -940,6 +918,36 @@ class DroidRelayService {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断请求是否启用 Anthropic 推理模式
|
||||||
|
*/
|
||||||
|
_isThinkingRequested(requestBody) {
|
||||||
|
const thinking = requestBody && typeof requestBody === 'object' ? requestBody.thinking : null
|
||||||
|
if (!thinking) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thinking === true) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof thinking === 'string') {
|
||||||
|
return thinking.trim().toLowerCase() === 'enabled'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof thinking === 'object') {
|
||||||
|
if (thinking.enabled === true) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof thinking.type === 'string') {
|
||||||
|
return thinking.type.trim().toLowerCase() === 'enabled'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理请求体(注入 system prompt 等)
|
* 处理请求体(注入 system prompt 等)
|
||||||
*/
|
*/
|
||||||
@@ -950,17 +958,6 @@ class DroidRelayService {
|
|||||||
const hasStreamField =
|
const hasStreamField =
|
||||||
requestBody && Object.prototype.hasOwnProperty.call(requestBody, 'stream')
|
requestBody && Object.prototype.hasOwnProperty.call(requestBody, 'stream')
|
||||||
|
|
||||||
const shouldDisableThinking =
|
|
||||||
endpointType === 'anthropic' && processedBody.__forceDisableThinking === true
|
|
||||||
|
|
||||||
if ('__forceDisableThinking' in processedBody) {
|
|
||||||
delete processedBody.__forceDisableThinking
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestBody && '__forceDisableThinking' in requestBody) {
|
|
||||||
delete requestBody.__forceDisableThinking
|
|
||||||
}
|
|
||||||
|
|
||||||
if (processedBody && Object.prototype.hasOwnProperty.call(processedBody, 'metadata')) {
|
if (processedBody && Object.prototype.hasOwnProperty.call(processedBody, 'metadata')) {
|
||||||
delete processedBody.metadata
|
delete processedBody.metadata
|
||||||
}
|
}
|
||||||
@@ -975,9 +972,7 @@ class DroidRelayService {
|
|||||||
processedBody.stream = true
|
processedBody.stream = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasTemperatureField = Object.prototype.hasOwnProperty.call(processedBody, 'temperature')
|
// Anthropic 端点:仅注入系统提示
|
||||||
|
|
||||||
// Anthropic 端点:处理 thinking 字段
|
|
||||||
if (endpointType === 'anthropic') {
|
if (endpointType === 'anthropic') {
|
||||||
if (this.systemPrompt) {
|
if (this.systemPrompt) {
|
||||||
const promptBlock = { type: 'text', text: this.systemPrompt }
|
const promptBlock = { type: 'text', text: this.systemPrompt }
|
||||||
@@ -992,43 +987,9 @@ class DroidRelayService {
|
|||||||
processedBody.system = [promptBlock]
|
processedBody.system = [promptBlock]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const reasoningLevel = shouldDisableThinking ? null : this._getReasoningLevel(requestBody)
|
|
||||||
if (reasoningLevel) {
|
|
||||||
const budgetTokens = {
|
|
||||||
low: 4096,
|
|
||||||
medium: 12288,
|
|
||||||
high: 24576
|
|
||||||
}
|
|
||||||
processedBody.thinking = {
|
|
||||||
type: 'enabled',
|
|
||||||
budget_tokens: budgetTokens[reasoningLevel]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
delete processedBody.thinking
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldDisableThinking) {
|
// OpenAI 端点:仅前置系统提示
|
||||||
if ('thinking' in processedBody) {
|
|
||||||
delete processedBody.thinking
|
|
||||||
}
|
|
||||||
} else if (processedBody.thinking && processedBody.thinking.type === 'enabled') {
|
|
||||||
if (hasTemperatureField) {
|
|
||||||
const parsedTemperature =
|
|
||||||
typeof processedBody.temperature === 'string'
|
|
||||||
? parseFloat(processedBody.temperature)
|
|
||||||
: processedBody.temperature
|
|
||||||
|
|
||||||
if (typeof parsedTemperature !== 'number' || Number.isNaN(parsedTemperature)) {
|
|
||||||
delete processedBody.temperature
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processedBody.temperature = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenAI 端点:处理 reasoning 字段
|
|
||||||
if (endpointType === 'openai') {
|
if (endpointType === 'openai') {
|
||||||
if (this.systemPrompt) {
|
if (this.systemPrompt) {
|
||||||
if (processedBody.instructions) {
|
if (processedBody.instructions) {
|
||||||
@@ -1039,16 +1000,6 @@ class DroidRelayService {
|
|||||||
processedBody.instructions = this.systemPrompt
|
processedBody.instructions = this.systemPrompt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const reasoningLevel = this._getReasoningLevel(requestBody)
|
|
||||||
if (reasoningLevel) {
|
|
||||||
processedBody.reasoning = {
|
|
||||||
effort: reasoningLevel,
|
|
||||||
summary: 'auto'
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
delete processedBody.reasoning
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理 temperature 和 top_p 参数
|
// 处理 temperature 和 top_p 参数
|
||||||
@@ -1064,26 +1015,6 @@ class DroidRelayService {
|
|||||||
return processedBody
|
return processedBody
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取推理级别(如果在 requestBody 中配置)
|
|
||||||
*/
|
|
||||||
_getReasoningLevel(requestBody) {
|
|
||||||
if (!requestBody || !requestBody.model) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const configured = this.modelReasoningMap.get(requestBody.model)
|
|
||||||
if (!configured) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!VALID_REASONING_LEVELS.has(configured)) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return configured
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理非流式响应
|
* 处理非流式响应
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user