mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-22 17:07:46 +08:00
refactor backend API structure
This commit is contained in:
@@ -1,87 +0,0 @@
|
||||
package util
|
||||
|
||||
import "ds2api/internal/config"
|
||||
|
||||
type StandardRequest struct {
|
||||
Surface string
|
||||
RequestedModel string
|
||||
ResolvedModel string
|
||||
ResponseModel string
|
||||
Messages []any
|
||||
HistoryText string
|
||||
ToolsRaw any
|
||||
FinalPrompt string
|
||||
ToolNames []string
|
||||
ToolChoice ToolChoicePolicy
|
||||
Stream bool
|
||||
Thinking bool
|
||||
Search bool
|
||||
RefFileIDs []string
|
||||
PassThrough map[string]any
|
||||
}
|
||||
|
||||
type ToolChoiceMode string
|
||||
|
||||
const (
|
||||
ToolChoiceAuto ToolChoiceMode = "auto"
|
||||
ToolChoiceNone ToolChoiceMode = "none"
|
||||
ToolChoiceRequired ToolChoiceMode = "required"
|
||||
ToolChoiceForced ToolChoiceMode = "forced"
|
||||
)
|
||||
|
||||
type ToolChoicePolicy struct {
|
||||
Mode ToolChoiceMode
|
||||
ForcedName string
|
||||
Allowed map[string]struct{}
|
||||
}
|
||||
|
||||
func DefaultToolChoicePolicy() ToolChoicePolicy {
|
||||
return ToolChoicePolicy{Mode: ToolChoiceAuto}
|
||||
}
|
||||
|
||||
func (p ToolChoicePolicy) IsNone() bool {
|
||||
return p.Mode == ToolChoiceNone
|
||||
}
|
||||
|
||||
func (p ToolChoicePolicy) IsRequired() bool {
|
||||
return p.Mode == ToolChoiceRequired || p.Mode == ToolChoiceForced
|
||||
}
|
||||
|
||||
func (p ToolChoicePolicy) Allows(name string) bool {
|
||||
if len(p.Allowed) == 0 {
|
||||
return true
|
||||
}
|
||||
_, ok := p.Allowed[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (r StandardRequest) CompletionPayload(sessionID string) map[string]any {
|
||||
modelID := r.ResolvedModel
|
||||
if modelID == "" {
|
||||
modelID = r.RequestedModel
|
||||
}
|
||||
modelType := "default"
|
||||
if resolvedType, ok := config.GetModelType(modelID); ok {
|
||||
modelType = resolvedType
|
||||
}
|
||||
refFileIDs := make([]any, 0, len(r.RefFileIDs))
|
||||
for _, fileID := range r.RefFileIDs {
|
||||
if fileID == "" {
|
||||
continue
|
||||
}
|
||||
refFileIDs = append(refFileIDs, fileID)
|
||||
}
|
||||
payload := map[string]any{
|
||||
"chat_session_id": sessionID,
|
||||
"model_type": modelType,
|
||||
"parent_message_id": nil,
|
||||
"prompt": r.FinalPrompt,
|
||||
"ref_file_ids": refFileIDs,
|
||||
"thinking_enabled": r.Thinking,
|
||||
"search_enabled": r.Search,
|
||||
}
|
||||
for k, v := range r.PassThrough {
|
||||
payload[k] = v
|
||||
}
|
||||
return payload
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package util
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestStandardRequestCompletionPayloadSetsModelTypeFromResolvedModel(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
model string
|
||||
thinking bool
|
||||
search bool
|
||||
modelType string
|
||||
}{
|
||||
{name: "default", model: "deepseek-v4-flash", thinking: false, search: false, modelType: "default"},
|
||||
{name: "expert", model: "deepseek-v4-pro", thinking: true, search: false, modelType: "expert"},
|
||||
{name: "vision", model: "deepseek-v4-vision-search", thinking: false, search: true, modelType: "vision"},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
req := StandardRequest{
|
||||
ResolvedModel: tc.model,
|
||||
FinalPrompt: "hello",
|
||||
Thinking: tc.thinking,
|
||||
Search: tc.search,
|
||||
RefFileIDs: []string{"file-a", "file-b"},
|
||||
PassThrough: map[string]any{
|
||||
"temperature": 0.3,
|
||||
},
|
||||
}
|
||||
|
||||
payload := req.CompletionPayload("session-123")
|
||||
|
||||
if got := payload["model_type"]; got != tc.modelType {
|
||||
t.Fatalf("expected model_type %s, got %#v", tc.modelType, got)
|
||||
}
|
||||
if got := payload["chat_session_id"]; got != "session-123" {
|
||||
t.Fatalf("unexpected chat_session_id: %#v", got)
|
||||
}
|
||||
if got := payload["thinking_enabled"]; got != tc.thinking {
|
||||
t.Fatalf("unexpected thinking_enabled: %#v", got)
|
||||
}
|
||||
if got := payload["search_enabled"]; got != tc.search {
|
||||
t.Fatalf("unexpected search_enabled: %#v", got)
|
||||
}
|
||||
if got := payload["temperature"]; got != 0.3 {
|
||||
t.Fatalf("expected passthrough temperature, got %#v", got)
|
||||
}
|
||||
refFileIDs, ok := payload["ref_file_ids"].([]any)
|
||||
if !ok {
|
||||
t.Fatalf("expected ref_file_ids slice, got %#v", payload["ref_file_ids"])
|
||||
}
|
||||
if len(refFileIDs) != 2 || refFileIDs[0] != "file-a" || refFileIDs[1] != "file-b" {
|
||||
t.Fatalf("unexpected ref_file_ids: %#v", refFileIDs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user