Workers AI integration drops output of non-streaming chat responses in the OpenAI format (`choices`)

Aberta Para iniciantes
#26,120 1 comentário 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
2/5
Tempo estimado
1-3 horas
Facilidade para iniciantes
78/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
typescript
Domínio
observability

Direção de pesquisa

Comece lendo packages/server-utils/src/ai/workers-ai/utils.ts e sua função addResponseAttributes; em seguida, compare o tratamento de streaming existente do Workers AI em ai/workers-ai/streaming.ts com o do OpenAI em ai/openai/utils.ts. Atualize o caminho sem streaming para capturar mensagens de saída, texto da resposta e motivos de finalização de choices; confirme que a resposta no novo formato registra esses atributos e preserva o formato de resposta anterior.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

Bug Cloudflare Workers Spans
Is there an existing issue for this?
  • I have checked for existing issues
How do you use Sentry?

Sentry SaaS (sentry.io)

Which SDK are you using?

@sentry/cloudflare

SDK Version

11.10.0 (@sentry/server-utils 11.10.0). The same code is on develop.

Framework Version

Cloudflare Workers, Workers AI binding

Steps to Reproduce
  1. Instrument the Workers AI binding (the default @sentry/cloudflare setup).

  2. Call a model that answers in the OpenAI chat-completion format, without stream: true. For example, @cf/google/gemma-4-26b-a4b-it:

    const result = await env.AI.run("@cf/google/gemma-4-26b-a4b-it", {
      messages: [{ role: "user", content: "Say hi" }],
      max_tokens: 50,
    });
    
  3. Open the gen_ai.chat span in Sentry.

Expected Result

The span has gen_ai.output.messages, gen_ai.response.text and gen_ai.response.finish_reasons, the same as for a stream: true call to the same model.

Actual Result

The span has the token usage, but no output and no finish reason.

I sent the same prompt to @cf/google/gemma-4-26b-a4b-it twice through the Workers AI REST API, once without and once with stream: true. Then I passed the real responses through instrumentWorkersAiClient (11.10.0). The gen_ai.* span attributes were:

--- no stream
gen_ai.operation.name = "chat"
gen_ai.usage.input_tokens = 19
gen_ai.usage.output_tokens = 4
gen_ai.usage.total_tokens = 23

--- stream: true
gen_ai.operation.name = "chat"
gen_ai.output.messages = "[{\"role\":\"assistant\",\"parts\":[{\"type\":\"text\",\"content\":\"Hello there!\"}]}]"
gen_ai.response.finish_reasons = "[\"stop\"]"
gen_ai.response.streaming = true
gen_ai.response.text = "Hello there!"
gen_ai.usage.input_tokens = 19
gen_ai.usage.output_tokens = 4
gen_ai.usage.total_tokens = 23

The non-streaming response was:

{"id":"...","object":"chat.completion","created":0,"model":"@cf/google/gemma-4-26b-a4b-it","choices":[{"index":0,"message":{"role":"assistant","content":"Hello there!"},"finish_reason":"stop","logprobs":null}],"usage":{"prompt_tokens":19,"completion_tokens":4,"total_tokens":23}}
Cause

Workers AI returns two response formats:

  • older models: { response: string, tool_calls?, usage }
  • newer models, such as gemma-4: the OpenAI chat-completion format with choices[].message

The streaming path supports both. instrumentWorkersAiStream in ai/workers-ai/streaming.ts reads parsed.response and also parsed.choices[].delta.content, delta.tool_calls and finish_reason.

The non-streaming path supports only the old format. addResponseAttributes in ai/workers-ai/utils.ts reads only response.response and response.tool_calls:

https://github.com/getsentry/sentry-javascript/blob/develop/packages/server-utils/src/ai/workers-ai/utils.ts

A possible fix: when response.choices is an array, read choices[].message.content, choices[].message.tool_calls and choices[].finish_reason, the same way as the OpenAI integration (ai/openai/utils.ts) does.

Additional Context

Workaround: we wrap the call in our own gen_ai.chat span that sets gen_ai.output.messages from choices, and we call env.AI.run inside Sentry.suppressTracing() so that the SDK span does not duplicate it.

Linguagem predominante
TypeScript
Estrelas
8.8k
Forks
1.9k
Merge médio
1d 20h
PRs com merge (30d)
682

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de getsentry/sentry-javascript

Todas as issues de getsentry/sentry-javascript

Issues semelhantes

Mais issues de TypeScript

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.