X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/7594b9938b7343717e7a57aa7aede5d40d547483..d9fddc0f506eb4ead7049f5638674b2b8773fcaa:/model.go?ds=inline diff --git a/model.go b/model.go index f15be22..7c85643 100644 --- a/model.go +++ b/model.go @@ -138,9 +138,11 @@ func (k ModelAPIKey) Authorize(ctx context.Context, header http.Header) error { // ChatGPT backend and the OpenAI API take the same request body and differ only // in the URL and the credentials. Every call sends the fixed cache key of the // agent, so the turns and the compactions of the agent share one prompt cache. -// The ChatGPT backend caches only with the key in the session_id header, so a -// call to it sends the key there and in the body. Every call is recorded in the -// usage file. +// A call of a subagent sends the key of the agent with "-" and the name of the +// subagent, so that the calls of a subagent do not share a cache entry with the +// calls of the agent that run at the same time. The ChatGPT backend caches only +// with the key in the session_id header, so a call to it sends the key there +// and in the body. Every call is recorded in the usage file. // // The request never holds max_output_tokens or metadata, because the ChatGPT // backend refuses them. It sets store to false, so the client sends the whole @@ -166,6 +168,16 @@ func (c *ModelClient) LimitReached() bool { return c.limit > 0 && c.calls.Load() >= c.limit } +// CallLimit returns the configured call limit, or zero for no limit. +func (c *ModelClient) CallLimit() int64 { + return c.limit +} + +// UsagePath returns the file that records the calls of this client. +func (c *ModelClient) UsagePath() string { + return c.usage.path +} + // Create sends the call and reads its event stream to the end. Over the call // limit it sends nothing and returns errModelCallLimit. func (c *ModelClient) Create(ctx context.Context, request ModelRequest) (ModelResponse, error) { @@ -173,6 +185,11 @@ func (c *ModelClient) Create(ctx context.Context, request ModelRequest) (ModelRe return ModelResponse{}, errModelCallLimit } + cacheKey := c.cacheKey + if request.Agent != "" { + cacheKey += "-" + request.Agent + } + body, err := json.Marshal(ModelRequestBody{ Model: request.Model, Instructions: request.Instructions, @@ -184,7 +201,7 @@ func (c *ModelClient) Create(ctx context.Context, request ModelRequest) (ModelRe Store: false, Stream: true, Include: []string{"reasoning.encrypted_content"}, - PromptCacheKey: c.cacheKey, + PromptCacheKey: cacheKey, }) if err != nil { return ModelResponse{}, fmt.Errorf("encode request: %w", err) @@ -204,7 +221,7 @@ func (c *ModelClient) Create(ctx context.Context, request ModelRequest) (ModelRe _, chatgpt := c.auth.(*ChatGPTAuth) if chatgpt { - httpRequest.Header.Set("session_id", c.cacheKey) + httpRequest.Header.Set("session_id", cacheKey) } start := time.Now() @@ -304,8 +321,9 @@ type ModelOutputItem struct { // modelUserMessage values or output items of an earlier response. Node names // the node that a compaction builds, or is nil. Turn names the request of a // turn: first or next. Agent names the subagent that makes the call, or is -// empty for a call of the agent itself. Node, Turn, and Agent go only to the -// usage file, never to the endpoint. +// empty for a call of the agent itself. Node, Turn, and Agent go to the usage +// file, never to the endpoint as fields. Agent also gives the call the cache +// key of its subagent. type ModelRequest struct { Model string Effort string