在实际应用中,一个 Agent 往往需要在多个模型之间做选择,例如:
aster 提供了一个轻量级的 Router 抽象,在不改变核心运行时的前提下,为模型选择增加一层路由能力。
pkg/router 提供了一个通用的 Router 接口:
type Router interface {
SelectModel(ctx context.Context, intent *RouteIntent) (*types.ModelConfig, error)
}
其中 RouteIntent 描述一次调用的“意图”:
type RouteIntent struct {
Task string // 任务类型,如 "chat"、"summarize"
Priority Priority // "latency" / "cost" / "quality"
TemplateID string // 当前 Agent 的模板 ID
Metadata map[string]interface{} // 预留的扩展信息
}
路由优先级使用简单的枚举:
const (
PriorityLatency Priority = "latency"
PriorityCost Priority = "cost"
PriorityQuality Priority = "quality"
)
在 AgentConfig 中,通过 RoutingProfile 字段指定路由偏好:
type AgentConfig struct {
TemplateID string `json:"template_id"`
RoutingProfile string `json:"routing_profile,omitempty"` // 例如 "cost" 或 "quality"
}
在 Agent 创建时,RoutingProfile 会被转换为 Priority 传给 Router。
当前版本内置了一个简单的静态路由实现 StaticRouter:
type StaticRouteEntry struct {
Task string
Priority Priority
Model *types.ModelConfig
}
type StaticRouter struct {
defaultModel *types.ModelConfig
routes []StaticRouteEntry
}
匹配规则:
defaultModel;defaultModel 都不存在,则返回错误。Router 是一个 可选依赖,通过 agent.Dependencies 注入:
deps := &agent.Dependencies{
Store: store,
SandboxFactory: sbFactory,
ToolRegistry: toolReg,
ProviderFactory: provider.NewMultiProviderFactory(),
Router: myRouter, // 可选
TemplateRegistry: tplRegistry,
}
在 agent.Create 中,如果配置了 Router:
AgentConfig 和模板构造默认的 ModelConfig;RouteIntent:intent := &router.RouteIntent{
Task: "chat",
Priority: router.Priority(config.RoutingProfile),
TemplateID: config.TemplateID,
Metadata: config.Metadata,
}
deps.Router.SelectModel(ctx, intent) 获取最终的 ModelConfig;ProviderFactory.Create 创建具体 Provider。如果没有配置 Router,则完全保持原有行为:使用 config.ModelConfig 或模板中的 Model。
完整示例参考:examples/router/main.go。
下面是一个简化示例片段:
defaultModel := &types.ModelConfig{
Provider: "anthropic",
Model: "claude-3-5-sonnet-20241022",
}
routes := []router.StaticRouteEntry{
{
Task: "chat",
Priority: router.PriorityQuality,
Model: &types.ModelConfig{
Provider: "anthropic",
Model: "claude-3-5-sonnet-20241022",
},
},
{
Task: "chat",
Priority: router.PriorityCost,
Model: &types.ModelConfig{
Provider: "deepseek",
Model: "deepseek-chat",
},
},
}
rt := router.NewStaticRouter(defaultModel, routes)
然后在创建 Agent 时指定不同的 RoutingProfile:
qualityAgent, _ := agent.Create(ctx, &types.AgentConfig{
TemplateID: "router-demo",
RoutingProfile: string(router.PriorityQuality),
}, deps)
costAgent, _ := agent.Create(ctx, &types.AgentConfig{
TemplateID: "router-demo",
RoutingProfile: string(router.PriorityCost),
}, deps)
两个 Agent 会在相同模板下,根据不同的路由偏好选择不同的模型。
当前 Router 设计遵循几个原则:
这使得 aster 可以在保持简单易用的同时,逐步向更完整的“模型路由”能力靠拢。