feat: publish sanitized custom.97 source

This commit is contained in:
cneicy committed 2026-10-27 20:43:39 +08:00
1 parent 8e6ed0317b
commit 86c0276156
1022 files changed
+69903 -19207

No files matched your search

+12 -3
View File
@@ -14,6 +14,7 @@ import (
relayconstant "github.com/QuantumNous/new-api/relay/constant"
"github.com/QuantumNous/new-api/relaykit/dto"
"github.com/QuantumNous/new-api/relaykit/types"
"github.com/QuantumNous/new-api/service"
"github.com/samber/lo"
"github.com/gin-gonic/gin"
@@ -22,9 +23,16 @@ import (
type Adaptor struct {
}
func (a *Adaptor) ConvertGeminiRequest(*gin.Context, *relaycommon.RelayInfo, *dto.GeminiChatRequest) (any, error) {
//TODO implement me
return nil, errors.New("not implemented")
func (a *Adaptor) ConvertGeminiRequest(c *gin.Context, info *relaycommon.RelayInfo, request *dto.GeminiChatRequest) (any, error) {
result, err := service.ConvertRequest(c, info, types.RelayFormatOpenAI, request)
if err != nil {
return nil, err
}
openaiRequest, ok := result.Value.(*dto.GeneralOpenAIRequest)
if !ok {
return nil, fmt.Errorf("expected OpenAI chat completions request, got %T", result.Value)
}
return a.ConvertOpenAIRequest(c, info, openaiRequest)
}
func (a *Adaptor) ConvertClaudeRequest(c *gin.Context, info *relaycommon.RelayInfo, req *dto.ClaudeRequest) (any, error) {
@@ -42,6 +50,7 @@ func (a *Adaptor) ConvertImageRequest(c *gin.Context, info *relaycommon.RelayInf
}
func (a *Adaptor) Init(info *relaycommon.RelayInfo) {
info.ConvOptions().WebSearch = encodeWebSearch(info)
}
func (a *Adaptor) GetRequestURL(info *relaycommon.RelayInfo) (string, error) {
+3 -3
View File
@@ -86,7 +86,7 @@ func zhipu4vImageHandler(c *gin.Context, resp *http.Response, info *relaycommon.
url = data.ImageUrl
}
if url == "" {
logger.LogWarn(c, "zhipu_image_missing_url")
logger.LogWarn(c, common.LogText("zhipu_image_missing_url"))
continue
}
@@ -99,14 +99,14 @@ func zhipu4vImageHandler(c *gin.Context, resp *http.Response, info *relaycommon.
default:
_, downloaded, err := service.GetImageFromUrl(url)
if err != nil {
logger.LogError(c, "zhipu_image_get_b64_failed: "+err.Error())
logger.LogError(c, common.LogText("zhipu_image_get_b64_failed: %s", err.Error()))
continue
}
b64 = downloaded
}
if b64 == "" {
logger.LogWarn(c, "zhipu_image_empty_b64")
logger.LogWarn(c, common.LogText("zhipu_image_empty_b64"))
continue
}
+10 -9
View File
@@ -42,15 +42,16 @@ func requestOpenAI2Zhipu(request dto.GeneralOpenAIRequest) *dto.GeneralOpenAIReq
Stop, _ = request.Stop.([]string)
}
out := &dto.GeneralOpenAIRequest{
Model: request.Model,
Stream: request.Stream,
Messages: messages,
Temperature: request.Temperature,
TopP: request.TopP,
Stop: Stop,
Tools: request.Tools,
ToolChoice: request.ToolChoice,
THINKING: request.THINKING,
Model: request.Model,
Stream: request.Stream,
Messages: messages,
Temperature: request.Temperature,
TopP: request.TopP,
Stop: Stop,
Tools: request.Tools,
ToolChoice: request.ToolChoice,
THINKING: request.THINKING,
ReasoningEffort: request.ReasoningEffort,
}
if request.MaxTokens != nil || request.MaxCompletionTokens != nil {
maxTokens := request.GetMaxTokens()
+85
View File
@@ -0,0 +1,85 @@
package zhipu_4v
import (
"github.com/QuantumNous/new-api/common"
relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/relaykit/dto"
"github.com/QuantumNous/new-api/relaykit/relayconvert/convmeta"
"github.com/QuantumNous/new-api/relaykit/types"
"github.com/tidwall/gjson"
)
// zhipuSearchEngine is the documented default search_engine. It is also the
// tool-price key of the searches billed on this path.
const zhipuSearchEngine = "search_std"
// encodeWebSearch maps hosted web search onto the GLM Chat web_search tool
// (https://docs.bigmodel.cn/api-reference/模型-api/对话补全). Claude and
// Responses clients reach Zhipu natively, so only the Chat target is handled.
// search_result makes non-stream responses carry the top-level web_search
// array; search_intent:false skips intent detection when the client forced
// the search.
func encodeWebSearch(info *relaycommon.RelayInfo) convmeta.WebSearchEncoder {
return func(call convmeta.WebSearchCall) (*convmeta.WebSearchEncoding, error) {
if call.Chat == nil {
return nil, nil
}
var diagnostics []types.ConversionDiagnostic
webSearch := map[string]any{"enable": true, "search_engine": zhipuSearchEngine, "search_result": true}
if call.Forced {
webSearch["search_intent"] = false
// Stream responses carry no search evidence; a forced search is
// the only proof that one ran. A non-stream web_search array
// confirms the same single call through zhipuChatToolUsage.
info.RecordRequestInferredToolCall(zhipuSearchEngine)
}
// Only searches this encoder requested are known to use search_std.
info.VendorToolUsage = zhipuChatToolUsage
spec := call.Spec
switch {
case len(spec.AllowedDomains) == 1:
webSearch["search_domain_filter"] = spec.AllowedDomains[0]
case len(spec.AllowedDomains) > 1:
diagnostics = append(diagnostics, call.SemanticLoss("unsupported_domain_filter", "GLM web_search accepts one search_domain_filter; the domain filter was dropped"))
}
if len(spec.BlockedDomains) > 0 {
diagnostics = append(diagnostics, call.SemanticLoss("unsupported_domain_filter", "GLM web_search cannot exclude domains; blocked_domains was dropped"))
}
if spec.MaxUses != nil {
diagnostics = append(diagnostics, call.SemanticLoss("unsupported_search_limit", "GLM web_search cannot preserve max_uses"))
}
if len(spec.AllowedCallers) > 0 || spec.ExternalWebAccess != nil {
diagnostics = append(diagnostics, call.SemanticLoss("unsupported_search_controls", "GLM web_search cannot preserve caller or external-access constraints"))
}
switch spec.SearchContextSize {
case "high":
webSearch["content_size"] = "high"
case "", "medium":
default:
diagnostics = append(diagnostics, call.PresentationLoss("unsupported_search_tuning", "GLM web_search content_size has no low setting"))
}
if spec.Location != nil || spec.ResponseInclusion != "" || len(spec.ReturnTokenBudget) > 0 {
diagnostics = append(diagnostics, call.PresentationLoss("unsupported_search_tuning", "GLM web_search cannot preserve location or result tuning"))
}
native, err := common.Marshal(map[string]any{"type": "web_search", "web_search": webSearch})
if err != nil {
return nil, err
}
return &convmeta.WebSearchEncoding{
Tool: dto.ToolCallRequest{Type: "web_search", Native: native},
Diagnostics: diagnostics,
}, nil
}
}
// zhipuChatToolUsage bills one search_std call when a non-stream GLM Chat
// response carries the top-level web_search result array. The array lists
// results, not searches, so its length is not a count.
func zhipuChatToolUsage(raw []byte) map[string]int {
results := gjson.GetBytes(raw, "web_search")
if !results.IsArray() || len(results.Array()) == 0 {
return nil
}
return map[string]int{zhipuSearchEngine: 1}
}