-
Notifications
You must be signed in to change notification settings - Fork 1.5k
refactor: use AI budget period from deployment config #27117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,7 @@ import ( | |
| coderdpubsub "github.com/coder/coder/v2/coderd/pubsub" | ||
| "github.com/coder/coder/v2/coderd/util/ptr" | ||
| "github.com/coder/coder/v2/codersdk" | ||
| "github.com/coder/quartz" | ||
| ) | ||
|
|
||
| var ( | ||
|
|
@@ -113,11 +114,15 @@ type Server struct { | |
| // budgetPolicy selects the effective group when a user belongs to multiple | ||
| // budgeted groups, used for cost attribution on token usage records. | ||
| budgetPolicy codersdk.AIBudgetPolicy | ||
| // budgetPeriod is the deployment-configured budgeting period used to | ||
| // derive the window over which user AI spend is aggregated. | ||
| budgetPeriod codersdk.AIBudgetPeriod | ||
| clock quartz.Clock | ||
| } | ||
|
|
||
| func NewServer(lifecycleCtx context.Context, store store, ps pubsub.Pubsub, logger slog.Logger, accessURL string, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: the number of args is starting to get unwieldy.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point 👍 This is a bigger change and touches a lot of files, including tests, so will address this in a follow-up PR. |
||
| bridgeCfg codersdk.AIBridgeConfig, externalAuthConfigs []*externalauth.Config, experiments codersdk.Experiments, | ||
| aiSeatTracker aiseats.SeatTracker, | ||
| aiSeatTracker aiseats.SeatTracker, clock quartz.Clock, | ||
| ) (*Server, error) { | ||
| eac := make(map[string]*externalauth.Config, len(externalAuthConfigs)) | ||
|
|
||
|
|
@@ -138,6 +143,8 @@ func NewServer(lifecycleCtx context.Context, store store, ps pubsub.Pubsub, logg | |
| structuredLogging: bridgeCfg.StructuredLogging.Value(), | ||
| aiSeatTracker: aiSeatTracker, | ||
| budgetPolicy: codersdk.NewAIBudgetPolicyFromString(bridgeCfg.BudgetPolicy), | ||
| budgetPeriod: codersdk.NewAIBudgetPeriodFromString(bridgeCfg.BudgetPeriod), | ||
| clock: clock, | ||
| } | ||
|
|
||
| if bridgeCfg.InjectCoderMCPTools { | ||
|
|
@@ -747,7 +754,8 @@ func (s *Server) IsAuthorized(ctx context.Context, in *proto.IsAuthorizedRequest | |
| } | ||
|
|
||
| // IsBudgetExceeded reports whether the user's AI spend has reached their | ||
| // effective limit over [PeriodStart, now]. | ||
| // effective limit over [periodStart, now], where periodStart is the start of | ||
| // the current deployment-configured budget period. | ||
| func (s *Server) IsBudgetExceeded(ctx context.Context, in *proto.IsBudgetExceededRequest) (*proto.IsBudgetExceededResponse, error) { | ||
| //nolint:gocritic // AIBridged has specific authz rules. | ||
| ctx = dbauthz.AsAIBridged(ctx) | ||
|
|
@@ -756,14 +764,13 @@ func (s *Server) IsBudgetExceeded(ctx context.Context, in *proto.IsBudgetExceede | |
| if err != nil { | ||
| return nil, xerrors.Errorf("invalid user_id %q: %w", in.GetUserId(), err) | ||
| } | ||
| // An unset PeriodStart deserializes to time.Unix(0, 0), which would | ||
| // incorrectly aggregate the user's lifetime spend against a period budget. | ||
| if in.PeriodStart == nil { | ||
| return nil, xerrors.New("period_start is required") | ||
|
|
||
| periodWindow, err := budget.CurrentPeriod(s.clock.Now(), s.budgetPeriod) | ||
| if err != nil { | ||
| return nil, xerrors.Errorf("compute AI budget period: %w", err) | ||
| } | ||
| periodStart := in.GetPeriodStart().AsTime() | ||
|
|
||
| userBudget, err := s.checkUserAIBudget(ctx, userID, periodStart) | ||
| userBudget, err := s.checkUserAIBudget(ctx, userID, periodWindow.Start) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This parameter was incorrectly introduced in #26915: the period should have been derived from the deployment config from the beginning. Since this change was not part of any release, my understanding is that we can safely remove the field without marking it as deprecated. This would only be a problem if we had a server and a client running with different proto versions: an old server that still requires
period_startreceiving a request from a new client (which no longer sends it) would reject the request. Let me know if that is not the case.