fix(anthropic): 映射 refusal 与 model_context_window_exceeded 两个 stop_reason - #70
Merged
Merged
Conversation
…p reasons Both stop reasons came out as FinishReasonUnknown. A response that filled the context window is truncated, as with max_tokens, so it is now FinishReasonLength. A refusal is a response the safety classifiers stopped; it is now FinishReasonContentFilter, which is what the Google, Completions and Responses providers report for their content filters. RawFinishReason is unchanged.
HoneyBBQ
marked this pull request as ready for review
September 30, 2026 06:53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
mapFinishReason没有处理 Anthropic 的model_context_window_exceeded和refusal两个stop_reason,两者都映射为FinishReasonUnknown。model_context_window_exceeded表示响应写满了模型的上下文窗口,官方文档要求按截断处理。Sonnet 4.5 及更新的模型不加 beta 头也会返回这个值。refusal表示安全分类器中止了响应,接口以 200 正常返回,不是错误。调用方按FinishReasonLength判断截断、按FinishReasonContentFilter判断拦截时,这两种情况都判断不出来。改动
model_context_window_exceeded映射为FinishReasonLength,与max_tokens相同。refusal映射为FinishReasonContentFilter。Google、Completions 和 Responses 的内容过滤也报告这个值。RawFinishReason仍是原始的stop_reason。docs/api-reference.md中FinishReasonLength的说明加上上下文窗口。验证
go build ./...、go vet ./...、go vet -tags integration ./...、go test ./... -short -count=1 -race和golangci-lint run ./...均通过,go mod tidy无 diff。TestFinishReasonMapping。对每个已映射的stop_reason,检查DoGenerate的结果以及DoStream的FinishStepPart和FinishPart,并断言RawFinishReason。改回原来的映射,model_context_window_exceeded和refusal两个用例失败。stop_reason。取值和含义依据官方文档 Handling stop reasons 和 anthropic-sdk-go 的StopReason枚举。