Merge pull request #1268 from QuantumNous/alpha

fix: gemini relay empty response
This commit is contained in:
Calcium-Ion
2025-06-20 02:31:11 +08:00
committed by GitHub
6 changed files with 264 additions and 119 deletions

View File

@@ -102,14 +102,14 @@ func GetAllChannels(c *gin.Context) {
typeCounts, _ := model.CountChannelsGroupByType()
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": gin.H{
"items": channelData,
"total": total,
"page": p,
"page_size": pageSize,
"type_counts": typeCounts,
"success": true,
"message": "",
"data": gin.H{
"items": channelData,
"total": total,
"page": p,
"page_size": pageSize,
"type_counts": typeCounts,
},
})
return
@@ -237,10 +237,20 @@ func SearchChannels(c *gin.Context) {
}
channelData = channels
}
// calculate type counts for search results
typeCounts := make(map[int64]int64)
for _, channel := range channelData {
typeCounts[int64(channel.Type)]++
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": channelData,
"data": gin.H{
"items": channelData,
"type_counts": typeCounts,
},
})
return
}

View File

@@ -46,6 +46,15 @@ func initCol() {
logGroupCol = commonGroupCol
logKeyCol = commonKeyCol
}
} else {
// LOG_SQL_DSN 为空时,日志数据库与主数据库相同
if common.UsingPostgreSQL {
logGroupCol = `"group"`
logKeyCol = `"key"`
} else {
logGroupCol = commonGroupCol
logKeyCol = commonKeyCol
}
}
// log sql type and database type
common.SysLog("Using Log SQL Type: " + common.LogSqlType)

View File

@@ -2,11 +2,12 @@ package model
import (
"errors"
"github.com/bytedance/gopkg/util/gopool"
"gorm.io/gorm"
"one-api/common"
"sync"
"time"
"github.com/bytedance/gopkg/util/gopool"
"gorm.io/gorm"
)
const (
@@ -48,6 +49,22 @@ func addNewRecord(type_ int, id int, value int) {
}
func batchUpdate() {
// check if there's any data to update
hasData := false
for i := 0; i < BatchUpdateTypeCount; i++ {
batchUpdateLocks[i].Lock()
if len(batchUpdateStores[i]) > 0 {
hasData = true
batchUpdateLocks[i].Unlock()
break
}
batchUpdateLocks[i].Unlock()
}
if !hasData {
return
}
common.SysLog("batch update started")
for i := 0; i < BatchUpdateTypeCount; i++ {
batchUpdateLocks[i].Lock()

View File

@@ -35,19 +35,6 @@ func GeminiTextGenerationHandler(c *gin.Context, resp *http.Response, info *rela
return nil, service.OpenAIErrorWrapper(err, "unmarshal_response_body_failed", http.StatusInternalServerError)
}
// 检查是否有候选响应
if len(geminiResponse.Candidates) == 0 {
return nil, &dto.OpenAIErrorWithStatusCode{
Error: dto.OpenAIError{
Message: "No candidates returned",
Type: "server_error",
Param: "",
Code: 500,
},
StatusCode: resp.StatusCode,
}
}
// 计算使用量(基于 UsageMetadata
usage := dto.Usage{
PromptTokens: geminiResponse.UsageMetadata.PromptTokenCount,

View File

@@ -165,8 +165,23 @@ func GeminiHelper(c *gin.Context) (openaiErr *dto.OpenAIErrorWithStatusCode) {
return service.OpenAIErrorWrapperLocal(err, "do_request_failed", http.StatusInternalServerError)
}
statusCodeMappingStr := c.GetString("status_code_mapping")
var httpResp *http.Response
if resp != nil {
httpResp = resp.(*http.Response)
relayInfo.IsStream = relayInfo.IsStream || strings.HasPrefix(httpResp.Header.Get("Content-Type"), "text/event-stream")
if httpResp.StatusCode != http.StatusOK {
openaiErr = service.RelayErrorHandler(httpResp, false)
// reset status code 重置状态码
service.ResetStatusCode(openaiErr, statusCodeMappingStr)
return openaiErr
}
}
usage, openaiErr := adaptor.DoResponse(c, resp.(*http.Response), relayInfo)
if openaiErr != nil {
service.ResetStatusCode(openaiErr, statusCodeMappingStr)
return openaiErr
}

View File

@@ -588,11 +588,10 @@ const TopUp = () => {
<Card
key={index}
onClick={() => selectPresetAmount(preset)}
className={`cursor-pointer !rounded-2xl transition-all hover:shadow-md ${
selectedPreset === preset.value
? 'border-blue-500'
: 'border-gray-200 hover:border-gray-300'
}`}
className={`cursor-pointer !rounded-2xl transition-all hover:shadow-md ${selectedPreset === preset.value
? 'border-blue-500'
: 'border-gray-200 hover:border-gray-300'
}`}
bodyStyle={{ textAlign: 'center' }}
>
<div className='font-medium text-lg flex items-center justify-center mb-1'>
@@ -661,54 +660,139 @@ const TopUp = () => {
/>
</div>
<div className='grid grid-cols-1 sm:grid-cols-2 gap-4'>
{/* <Button
type='primary'
onClick={() => preTopUp('zfb')}
size='large'
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === 'zfb'}
icon={<SiAlipay size={18} />}
style={{ height: '44px' }}
>
<span className='ml-2'>{t('支付宝')}</span>
</Button>
<Button
type='primary'
onClick={() => preTopUp('wx')}
size='large'
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === 'wx'}
icon={<SiWechat size={18} />}
style={{ height: '44px' }}
>
<span className='ml-2'>{t('微信')}</span>
</Button> */}
{payMethods.map((payMethod) => (
<Button
key={payMethod.type}
type='primary'
onClick={() => preTopUp(payMethod.type)}
size='large'
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === payMethod.type}
icon={
payMethod.type === 'zfb' ? (
<SiAlipay size={18} />
) : payMethod.type === 'wx' ? (
<SiWechat size={18} />
) : (
<CreditCard size={18} />
)
}
style={{
height: '44px',
color: payMethod.color,
}}
>
<span className='ml-2'>{payMethod.name}</span>
</Button>
))}
<div>
<Text strong className='block mb-3'>
{t('选择支付方式')}
</Text>
{payMethods.length === 2 ? (
<div className='grid grid-cols-1 sm:grid-cols-2 gap-3'>
{payMethods.map((payMethod) => (
<Button
key={payMethod.type}
type='primary'
onClick={() => preTopUp(payMethod.type)}
size='large'
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === payMethod.type}
icon={
payMethod.type === 'zfb' ? (
<SiAlipay size={16} />
) : payMethod.type === 'wx' ? (
<SiWechat size={16} />
) : (
<CreditCard size={16} />
)
}
style={{
height: '40px',
color: payMethod.color,
}}
className='transition-all hover:shadow-md w-full'
>
<span className='ml-1'>{payMethod.name}</span>
</Button>
))}
</div>
) : payMethods.length === 3 ? (
<div className='grid grid-cols-1 sm:grid-cols-3 gap-3'>
{payMethods.map((payMethod) => (
<Button
key={payMethod.type}
type='primary'
onClick={() => preTopUp(payMethod.type)}
size='large'
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === payMethod.type}
icon={
payMethod.type === 'zfb' ? (
<SiAlipay size={16} />
) : payMethod.type === 'wx' ? (
<SiWechat size={16} />
) : (
<CreditCard size={16} />
)
}
style={{
height: '40px',
color: payMethod.color,
}}
className='transition-all hover:shadow-md w-full'
>
<span className='ml-1'>{payMethod.name}</span>
</Button>
))}
</div>
) : payMethods.length > 3 ? (
<div className='grid grid-cols-2 sm:grid-cols-4 gap-3'>
{payMethods.map((payMethod) => (
<Card
key={payMethod.type}
onClick={() => preTopUp(payMethod.type)}
disabled={!enableOnlineTopUp}
className={`cursor-pointer !rounded-xl p-0 transition-all hover:shadow-md ${paymentLoading && payWay === payMethod.type
? 'border-blue-400'
: 'border-gray-200 hover:border-gray-300'
}`}
bodyStyle={{
padding: '10px',
textAlign: 'center',
opacity: !enableOnlineTopUp ? 0.5 : 1
}}
>
{paymentLoading && payWay === payMethod.type ? (
<div className='flex flex-col items-center justify-center h-full'>
<div className='mb-1'>
<div className='animate-spin rounded-full h-4 w-4 border-b-2 border-blue-500'></div>
</div>
<div className='text-xs text-gray-500'>{t('处理中')}</div>
</div>
) : (
<>
<div className='flex items-center justify-center mb-1'>
{payMethod.type === 'zfb' ? (
<SiAlipay size={20} color={payMethod.color} />
) : payMethod.type === 'wx' ? (
<SiWechat size={20} color={payMethod.color} />
) : (
<CreditCard size={20} color={payMethod.color} />
)}
</div>
<div className='text-sm font-medium'>{payMethod.name}</div>
</>
)}
</Card>
))}
</div>
) : (
<div className='grid grid-cols-1 gap-3'>
{payMethods.map((payMethod) => (
<Button
key={payMethod.type}
type='primary'
onClick={() => preTopUp(payMethod.type)}
size='large'
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === payMethod.type}
icon={
payMethod.type === 'zfb' ? (
<SiAlipay size={16} />
) : payMethod.type === 'wx' ? (
<SiWechat size={16} />
) : (
<CreditCard size={16} />
)
}
style={{
height: '40px',
color: payMethod.color,
}}
className='transition-all hover:shadow-md w-full'
>
<span className='ml-1'>{payMethod.name}</span>
</Button>
))}
</div>
)}
</div>
</div>
</>
@@ -941,48 +1025,71 @@ const TopUp = () => {
/>
</div>
<div className='grid grid-cols-2 gap-4'>
{/* <Button
type='primary'
onClick={() => preTopUp('zfb')}
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === 'zfb'}
icon={<SiAlipay size={18} />}
>
<span className='ml-2'>{t('支付宝')}</span>
</Button>
<Button
type='primary'
onClick={() => preTopUp('wx')}
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === 'wx'}
icon={<SiWechat size={18} />}
>
<span className='ml-2'>{t('微信')}</span>
</Button> */}
{payMethods.map((payMethod) => (
<Button
key={payMethod.type}
type='primary'
onClick={() => preTopUp(payMethod.type)}
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === payMethod.type}
icon={
payMethod.type === 'zfb' ? (
<SiAlipay size={18} />
) : payMethod.type === 'wx' ? (
<SiWechat size={18} />
) : (
<CreditCard size={18} />
)
}
style={{
color: payMethod.color,
}}
>
<span className='ml-2'>{payMethod.name}</span>
</Button>
))}
<div>
{payMethods.length === 2 ? (
<div className='grid grid-cols-2 gap-3'>
{payMethods.map((payMethod) => (
<Button
key={payMethod.type}
type='primary'
onClick={() => preTopUp(payMethod.type)}
disabled={!enableOnlineTopUp}
loading={paymentLoading && payWay === payMethod.type}
icon={
payMethod.type === 'zfb' ? (
<SiAlipay size={16} />
) : payMethod.type === 'wx' ? (
<SiWechat size={16} />
) : (
<CreditCard size={16} />
)
}
style={{
color: payMethod.color,
}}
className='h-10'
>
<span className='ml-1'>{payMethod.name}</span>
</Button>
))}
</div>
) : (
<div className='grid grid-cols-4 gap-2'>
{payMethods.map((payMethod) => (
<Card
key={payMethod.type}
onClick={() => preTopUp(payMethod.type)}
disabled={!enableOnlineTopUp}
className={`cursor-pointer !rounded-xl p-0 transition-all ${paymentLoading && payWay === payMethod.type
? 'border-blue-400'
: 'border-gray-200'
}`}
bodyStyle={{
padding: '8px',
textAlign: 'center',
opacity: !enableOnlineTopUp ? 0.5 : 1
}}
>
{paymentLoading && payWay === payMethod.type ? (
<div className='animate-spin rounded-full h-4 w-4 border-b-2 border-blue-500 mx-auto'></div>
) : (
<>
<div className='flex justify-center'>
{payMethod.type === 'zfb' ? (
<SiAlipay size={18} color={payMethod.color} />
) : payMethod.type === 'wx' ? (
<SiWechat size={18} color={payMethod.color} />
) : (
<CreditCard size={18} color={payMethod.color} />
)}
</div>
<div className='text-xs mt-1'>{payMethod.name}</div>
</>
)}
</Card>
))}
</div>
)}
</div>
</div>
</div>