Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion backend/docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1545,7 +1545,7 @@ const docTemplate = `{
},
{
"type": "string",
"description": "路由状态:active/inactive/unbound",
"description": "路由状态:bound/active/inactive",
"name": "route_status",
"in": "query"
},
Expand Down Expand Up @@ -8900,6 +8900,10 @@ const docTemplate = `{
"inactive"
]
},
"systemPrompt": {
"type": "string",
"maxLength": 20000
},
"vendor": {
"type": "string",
"maxLength": 64
Expand Down Expand Up @@ -9209,6 +9213,9 @@ const docTemplate = `{
"status": {
"type": "string"
},
"systemPrompt": {
"type": "string"
},
"updatedAt": {
"type": "string"
},
Expand Down Expand Up @@ -9516,6 +9523,10 @@ const docTemplate = `{
"inactive"
]
},
"systemPrompt": {
"type": "string",
"maxLength": 20000
},
"vendor": {
"type": "string",
"maxLength": 64
Expand Down
13 changes: 12 additions & 1 deletion backend/docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -1538,7 +1538,7 @@
},
{
"type": "string",
"description": "路由状态:active/inactive/unbound",
"description": "路由状态:bound/active/inactive",
"name": "route_status",
"in": "query"
},
Expand Down Expand Up @@ -8893,6 +8893,10 @@
"inactive"
]
},
"systemPrompt": {
"type": "string",
"maxLength": 20000
},
"vendor": {
"type": "string",
"maxLength": 64
Expand Down Expand Up @@ -9202,6 +9206,9 @@
"status": {
"type": "string"
},
"systemPrompt": {
"type": "string"
},
"updatedAt": {
"type": "string"
},
Expand Down Expand Up @@ -9509,6 +9516,10 @@
"inactive"
]
},
"systemPrompt": {
"type": "string",
"maxLength": 20000
},
"vendor": {
"type": "string",
"maxLength": 64
Expand Down
10 changes: 9 additions & 1 deletion backend/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1544,6 +1544,9 @@ definitions:
- active
- inactive
type: string
systemPrompt:
maxLength: 20000
type: string
vendor:
maxLength: 64
type: string
Expand Down Expand Up @@ -1757,6 +1760,8 @@ definitions:
type: integer
status:
type: string
systemPrompt:
type: string
updatedAt:
type: string
vendor:
Expand Down Expand Up @@ -1960,6 +1965,9 @@ definitions:
- active
- inactive
type: string
systemPrompt:
maxLength: 20000
type: string
vendor:
maxLength: 64
type: string
Expand Down Expand Up @@ -4306,7 +4314,7 @@ paths:
in: query
name: q
type: string
- description: 路由状态:active/inactive/unbound
- description: 路由状态:bound/active/inactive
in: query
name: route_status
type: string
Expand Down
1 change: 1 addition & 0 deletions backend/internal/application/channel/dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ type ModelView struct {
KindsJSON string
Icon string
CapabilitiesJSON string
SystemPrompt string
Status string
Description string
SortOrder int
Expand Down
2 changes: 2 additions & 0 deletions backend/internal/application/channel/errs.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ var (
ErrInvalidUpstreamBaseURL = errors.New("invalid upstream base url")
// ErrInvalidKinds 模型类型无效。
ErrInvalidKinds = errors.New("invalid kinds")
// ErrSystemPromptTooLong 系统提示词长度超过允许范围。
ErrSystemPromptTooLong = errors.New("system prompt too long")
// ErrInvalidModelOrder 模型排序参数无效。
ErrInvalidModelOrder = errors.New("invalid model order")
// ErrProtocolRequired 无法通过瀑布规则推断协议。
Expand Down
2 changes: 2 additions & 0 deletions backend/internal/application/channel/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type CreateModelInput struct {
KindsJSON string
Icon string
CapabilitiesJSON string
SystemPrompt string
Status string
Description string
}
Expand All @@ -56,6 +57,7 @@ type UpdateModelInput struct {
KindsJSON *string
Icon *string
CapabilitiesJSON *string
SystemPrompt *string
Status *string
Description *string
}
Expand Down
1 change: 1 addition & 0 deletions backend/internal/application/channel/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type ResolvedRoute struct {
ModelVendor string
ModelIcon string
ModelCapabilitiesJSON string
ModelSystemPrompt string
UpstreamModel string
UpstreamCbFailureThreshold int
UpstreamCbModelThreshold int
Expand Down
1 change: 1 addition & 0 deletions backend/internal/application/channel/service_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func toModelView(item repository.ChannelModelListRow) ModelView {
KindsJSON: item.KindsJSON,
Icon: item.Icon,
CapabilitiesJSON: item.CapabilitiesJSON,
SystemPrompt: item.SystemPrompt,
Status: item.Status,
Description: item.Description,
SortOrder: item.SortOrder,
Expand Down
14 changes: 14 additions & 0 deletions backend/internal/application/channel/service_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
// 模型管理
// ---------------------------------------------------------------------------

const maxSystemPromptChars = 20000

// ListModelsInput 定义模型列表筛选排序条件。
type ListModelsInput struct {
Query string
Expand Down Expand Up @@ -220,13 +222,18 @@ func (s *Service) CreateModel(ctx context.Context, input CreateModelInput) (*Mod
if err := validateOptionalJSON(strings.TrimSpace(input.CapabilitiesJSON)); err != nil {
return nil, ErrInvalidJSONConfig
}
systemPrompt := strings.TrimSpace(input.SystemPrompt)
if len([]rune(systemPrompt)) > maxSystemPromptChars {
return nil, ErrSystemPromptTooLong
}

item := &domainchannel.PlatformModel{
PlatformModelName: platformModelName,
Vendor: normalizeModelVendor(input.Vendor, platformModelName),
KindsJSON: kindsJSON,
Icon: normalizeModelIcon(input.Icon, input.Vendor, platformModelName),
CapabilitiesJSON: strings.TrimSpace(input.CapabilitiesJSON),
SystemPrompt: systemPrompt,
Status: normalizeStatus(input.Status),
Description: strings.TrimSpace(input.Description),
}
Expand Down Expand Up @@ -281,6 +288,13 @@ func (s *Service) UpdateModel(ctx context.Context, modelID uint, input UpdateMod
}
update.CapabilitiesJSON = &normalized
}
if input.SystemPrompt != nil {
systemPrompt := strings.TrimSpace(*input.SystemPrompt)
if len([]rune(systemPrompt)) > maxSystemPromptChars {
return nil, ErrSystemPromptTooLong
}
update.SystemPrompt = &systemPrompt
}
if input.Status != nil {
status := normalizeStatus(*input.Status)
update.Status = &status
Expand Down
1 change: 1 addition & 0 deletions backend/internal/application/channel/service_routing.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ func buildResolvedRoute(row repository.ChannelUpstreamRouteRow, apiKey string) *
ModelVendor: strings.TrimSpace(row.ModelVendor),
ModelIcon: strings.TrimSpace(row.ModelIcon),
ModelCapabilitiesJSON: strings.TrimSpace(row.ModelCapabilitiesJSON),
ModelSystemPrompt: strings.TrimSpace(row.ModelSystemPrompt),
UpstreamModel: strings.TrimSpace(row.UpstreamModelName),
UpstreamCbFailureThreshold: row.UpstreamCbFailureThreshold,
UpstreamCbModelThreshold: row.UpstreamCbModelThreshold,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
type ContextSlotKind string

const (
SlotSystemPrompt ContextSlotKind = "system_prompt"
SlotPreference ContextSlotKind = "preference"
SlotMemory ContextSlotKind = "memory"
SlotSnapshot ContextSlotKind = "snapshot"
Expand All @@ -24,6 +25,7 @@ const (
// slotPriority 优先级硬编码:数值越大越优先保留。
var slotPriority = map[ContextSlotKind]int{
SlotInput: 100,
SlotSystemPrompt: 95,
SlotPreference: 90,
SlotSnapshot: 80,
SlotRAG: 70,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,14 @@ func (s *Service) sendMessageInternal(

// ContextAssembler 只承载真正的系统级行为指令;资料型上下文稍后进入用户 XML。
assembler := NewContextAssembler(int64(cfg.ContextMaxInputTokens))
systemPrompt := resolveSystemPromptInjection(cfg, route)
if systemPrompt.Content != "" {
if systemPrompt.InlineToUser {
historyMsgs = inlineSystemPromptIntoLatestUserMessage(historyMsgs, systemPrompt.Content)
} else {
assembler.Add(ContextSlot{Kind: SlotSystemPrompt, Content: systemPrompt.Content, Required: true})
}
}
userCtx := userContextInput{}
var prefixMemories []domainmemory.UserMemory
if prefetch.snapshot != nil {
Expand Down
Loading
Loading