-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat(llmloop): add grace round after tool-request budget exhausted #872
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 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -303,10 +303,70 @@ func (r *Runner) RunPerFile(ctx context.Context, messages []llm.Message, newPath | |
|
|
||
| if stop == StopMaxRounds { | ||
| fmt.Fprintf(stdout.Writer(), "[ocr] Max tool requests reached for %s.\n", newPath) | ||
| r.runGraceRound(ctx, messages, newPath, sessionID) | ||
| } | ||
| return false, stop, nil | ||
| } | ||
|
|
||
| // runGraceRound performs one final LLM call after the tool-request budget is | ||
| // exhausted, giving the model a chance to submit any findings it identified | ||
| // but did not yet report via code_comment. | ||
| func (r *Runner) runGraceRound(ctx context.Context, messages []llm.Message, newPath string, sessionID string) { | ||
| graceDefs := graceRoundToolDefs(r.deps.MainToolDefs) | ||
| if len(graceDefs) == 0 { | ||
| return | ||
| } | ||
|
|
||
| messages = append(messages, llm.NewTextMessage("user", | ||
| "Your tool-call budget is exhausted. This is your FINAL round. You may ONLY:\n"+ | ||
| "- Call code_comment to submit any findings you have identified but not yet reported.\n"+ | ||
| "- Call task_done if you have nothing more to report.\n"+ | ||
| "No other tools are available. Do not attempt further analysis.")) | ||
|
|
||
| resp, err := r.deps.LLMClient.CompletionsWithCtx(ctx, llm.ChatRequest{ | ||
| Model: r.deps.Model, | ||
| Messages: messages, | ||
| Tools: graceDefs, | ||
|
Collaborator
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. Restricting the tool list for this final call will likely cost us the whole KV cache prefix. Placing the tool list in or next to the system prompt is the mainstream practice among current LLMs, precisely so that the prefix cache keeps hitting across a session. Swapping The timing makes it expensive: That said, there's a genuine trade-off here between effectiveness and cost. Narrowing the tool list is a hard constraint, whereas leaving |
||
| MaxTokens: r.deps.Template.CompletionTokenLimit(), | ||
| SessionID: sessionID, | ||
| }) | ||
| if err != nil { | ||
| fmt.Fprintf(stdout.Writer(), "[ocr] Grace round LLM error for %s: %v\n", newPath, err) | ||
| return | ||
| } | ||
|
|
||
| if resp.Usage != nil { | ||
| atomic.AddInt64(&r.totalInputTokens, resp.Usage.PromptTokens) | ||
| atomic.AddInt64(&r.totalOutputTokens, resp.Usage.CompletionTokens) | ||
| atomic.AddInt64(&r.totalCacheReadTokens, resp.Usage.CacheReadTokens) | ||
| atomic.AddInt64(&r.totalCacheWriteTokens, resp.Usage.CacheWriteTokens) | ||
| } | ||
|
|
||
| calls := resp.ToolCalls() | ||
| if len(calls) == 0 { | ||
| return | ||
| } | ||
|
|
||
| fs := r.deps.Session.GetOrCreateFileSession(newPath) | ||
| rec := fs.AppendTaskRecord(session.MainTask, nil) | ||
| thinking := resp.ReasoningContent() | ||
| for _, call := range calls { | ||
| r.executeToolCall(ctx, newPath, call, rec, thinking) | ||
| } | ||
|
lizhengfeng101 marked this conversation as resolved.
|
||
| } | ||
|
|
||
| // graceRoundToolDefs returns the subset of tool definitions containing only | ||
| // code_comment and task_done. | ||
| func graceRoundToolDefs(defs []llm.ToolDef) []llm.ToolDef { | ||
| out := make([]llm.ToolDef, 0, 2) | ||
| for _, d := range defs { | ||
| if d.Function.Name == "code_comment" || d.Function.Name == "task_done" { | ||
| out = append(out, d) | ||
| } | ||
| } | ||
| return out | ||
| } | ||
|
|
||
| // executeToolCall dispatches a single tool call from the LLM response and | ||
| // records the result in session history. code_comment handling includes | ||
| // optional async dispatch through CommentWorkerPool plus line-number | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.