feat: sync deployed v1.0.0-rc.38-custom.67
This commit is contained in:
1 parent
d2e03ab7e8
commit
ffc8cf56db
154 files changed
+39540
-20509
No files matched your search
@@ -1,21 +1,30 @@
|
||||
// Numerical fingerprint scorer adapted from Katao123/gpt-model-check (MIT),
|
||||
// commit 3d6716a0903cf061daea001d5d44ee410846634e. See the adjacent licenses.
|
||||
// ModelTrace scorer and bank: xqy2006/ModelTrace d4131b30243dfa05e70180b5eedde742103f1d73 (MIT).
|
||||
package model_fingerprint
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
_ "embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/QuantumNous/new-api/common"
|
||||
"github.com/grafana/sobek"
|
||||
)
|
||||
|
||||
const Model = "gpt-6-astra"
|
||||
const Version = "modeltrace-20260905-gmc-3d6716a"
|
||||
const Version = "modeltrace-d4131b3"
|
||||
|
||||
const ProbeCount = 3
|
||||
const OutputTokens = 4096
|
||||
|
||||
//go:embed bank.json
|
||||
var bankJSON string
|
||||
@@ -39,43 +48,71 @@ type Candidate struct {
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
Status string `json:"status"`
|
||||
ValidSamples int `json:"valid_samples"`
|
||||
Closest string `json:"closest,omitempty"`
|
||||
Weight float64 `json:"relative_weight,omitempty"`
|
||||
Gap float64 `json:"score_gap,omitempty"`
|
||||
Engine string `json:"engine"`
|
||||
Matches map[string]float64 `json:"matches,omitempty"`
|
||||
Status string `json:"status"`
|
||||
ValidSamples int `json:"valid_samples"`
|
||||
Closest string `json:"closest,omitempty"`
|
||||
Weight float64 `json:"relative_weight,omitempty"`
|
||||
Gap float64 `json:"score_gap,omitempty"`
|
||||
}
|
||||
|
||||
func ValidArray(text string, count int) bool {
|
||||
if len(text) > 16384 || count <= 0 {
|
||||
return false
|
||||
}
|
||||
text = strings.TrimSpace(text)
|
||||
if strings.HasPrefix(text, "```") && strings.HasSuffix(text, "```") {
|
||||
if i := strings.IndexByte(text, '\n'); i >= 0 {
|
||||
text = strings.TrimSpace(text[i+1 : len(text)-3])
|
||||
}
|
||||
}
|
||||
var numbers []int
|
||||
if common.Unmarshal([]byte(text), &numbers) != nil {
|
||||
return false
|
||||
}
|
||||
if len(numbers) < max(80, int(math.Ceil(float64(count)*.55))) || len(numbers) > count*2 {
|
||||
return false
|
||||
}
|
||||
for _, number := range numbers {
|
||||
if number < 1 || number > 355 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
type Probe struct {
|
||||
ID string
|
||||
System string
|
||||
Prompt string
|
||||
Count int
|
||||
}
|
||||
|
||||
func ProbeAt(index int) (Probe, error) {
|
||||
if index < 0 || index >= ProbeCount {
|
||||
return Probe{}, errors.New("invalid probe index")
|
||||
}
|
||||
// Disjoint length ranges retain three independent, non-identical challenges.
|
||||
offset, err := rand.Int(rand.Reader, big.NewInt(13))
|
||||
if err != nil {
|
||||
return Probe{}, err
|
||||
}
|
||||
count := 292 + index*14 + int(offset.Int64())
|
||||
prompt := fmt.Sprintf("这是一次独立的数值选择记录。逐项选择 %d 个 1 到 355(含端点)的整数。", count) +
|
||||
"每个位置都要单独选择;不要从 1 开始计数,不要连续递增或递减,也不要采用等差、循环、重复区块或其他规则化模式。" +
|
||||
"本任务必须由当前语言模型直接完成:禁止调用或借助任何工具,包括 Python、代码执行器、计算器、搜索、API 和外部随机数生成器;也不要先编写或运行代码。" +
|
||||
"偶然重复是有效的;不要重新排列或修正已经写出的项目。数字之间用逗号或空格分隔均可。直接从第一个取值开始输出,不要在序列前重复数量、范围或任务说明。"
|
||||
return Probe{ID: fmt.Sprint(index), Prompt: prompt, Count: count}, nil
|
||||
}
|
||||
|
||||
var integerPattern = regexp.MustCompile(`[0-9]+`)
|
||||
|
||||
// Match ModelTrace's longest numeric run parser; prose separates runs.
|
||||
func ValidArray(text string, count int) bool {
|
||||
if len(text) > 16384 || !utf8.ValidString(text) || count < 0 {
|
||||
return false
|
||||
}
|
||||
longest, current, end := 0, 0, 0
|
||||
for _, span := range integerPattern.FindAllStringIndex(text, -1) {
|
||||
if strings.ContainsFunc(text[end:span[0]], unicode.IsLetter) {
|
||||
current = 0
|
||||
}
|
||||
value, err := strconv.Atoi(text[span[0]:span[1]])
|
||||
if err == nil && value >= 1 && value <= 355 {
|
||||
current++
|
||||
}
|
||||
longest = max(longest, current)
|
||||
end = span[1]
|
||||
}
|
||||
return longest >= max(80, int(math.Ceil(float64(count)*.55)))
|
||||
}
|
||||
|
||||
func ValidSample(text string) bool { return ValidArray(text, 0) }
|
||||
|
||||
func Decide(candidates []Candidate, valid int) Result {
|
||||
r := Result{Status: "inconclusive", ValidSamples: valid}
|
||||
r := Result{Status: "inconclusive", Engine: Version, ValidSamples: valid, Matches: map[string]float64{}}
|
||||
if len(candidates) < 2 {
|
||||
return r
|
||||
}
|
||||
for _, candidate := range candidates {
|
||||
r.Matches[candidate.Model] = candidate.Weight
|
||||
}
|
||||
top := candidates[0]
|
||||
r.Closest = top.Model
|
||||
r.Weight = top.Weight
|
||||
@@ -98,6 +135,9 @@ func Decide(candidates []Candidate, valid int) Result {
|
||||
// Score runs only the embedded, pinned scorer. No filesystem, network or host
|
||||
// functions are exposed to the VM; upstream text is data, never JavaScript.
|
||||
func Score(samples []Sample) (Result, error) {
|
||||
if len(samples) > ProbeCount {
|
||||
return Result{}, errors.New("too many fingerprint samples")
|
||||
}
|
||||
valid := make([]Sample, 0, 3)
|
||||
for _, sample := range samples {
|
||||
if ValidArray(sample.Text, sample.Count) {
|
||||
@@ -105,7 +145,7 @@ func Score(samples []Sample) (Result, error) {
|
||||
}
|
||||
}
|
||||
if len(valid) == 0 {
|
||||
return Result{Status: "inconclusive"}, nil
|
||||
return Result{Status: "inconclusive", Engine: Version}, nil
|
||||
}
|
||||
compileOnce.Do(func() {
|
||||
program, compileErr = sobek.Compile("fingerprint", strings.ReplaceAll(scorerJS, "export ", ""), true)
|
||||
|
||||
Reference in new issue
Block a user