DatabricksAdapter yields text content during tool-calling rounds, causing response duplication

Đang mở
#421 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 3 ngày

Chưa có ai nhận issue này.

  • #436 của @MarioCadenas — đã đóng, không merge

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
55/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Ít trao đổi
Công nghệ
typescript
Lĩnh vực
ai, api, backend

Hướng nghiên cứu

Bắt đầu với streamCompletion() của DatabricksAdapter và phương thức run() quanh dòng 196, sau đó tái hiện vấn đề với maxSteps: 10 và nhiều công cụ như describeTable và executeSql. Theo dõi các sự kiện message_delta và tool-call trong suốt một lượt gọi công cụ. Hoàn thành có nghĩa là văn bản trung gian không tạo ra các câu trả lời trùng lặp hiển thị cho người dùng, trong khi phản hồi cuối cùng vẫn xuất hiện đúng một lần.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

DatabricksAdapter yields text content during tool-calling rounds, causing response duplication

Problem

When using DatabricksAdapter with Claude models via Databricks Model Serving (OpenAI-compatible endpoint), the model produces substantial text content alongside tool calls in the same response turn. The adapter's streamCompletion() method yields all delta.content text as message_delta events regardless of whether the same response also contains tool calls.

In a multi-step ReAct loop, this causes the model's intermediate text (which often includes the full answer) to be emitted and displayed to the user on every tool-calling turn — resulting in the same answer appearing 3-4× in the final output.

Root Cause Analysis

Claude's native API uses a trained-in tool-use system prompt that shapes the model to produce brief commentary before tool_use blocks. The Databricks OpenAI-compatible translation layer does not include this trained-in prompt, so Claude produces more verbose text during tool-calling rounds.

The adapter loop (run() method, line ~196) correctly breaks when no tool calls are present, but during tool-calling rounds, streamCompletion() yields ALL delta.content as message_delta events — there's no mechanism to suppress or buffer text that arrives in a turn that also contains tool calls.

Expected Behavior

Text content from tool-calling rounds should either:

  1. Be suppressed (not yielded as message_delta) when the same response also contains tool_calls
  2. Be buffered until streamCompletion returns, and only yielded if no tool calls were detected
  3. Be marked with metadata so consumers can distinguish intermediate text from final-answer text
Current Workaround

We added:

  • A system prompt instruction telling the model to only write brief status notes during tool-calling turns
  • Client-side text buffering in the SSE transport layer that discards accumulated text when a function_call event arrives in the same round
Environment
  • AppKit version: 0.38.1
  • Model: databricks-claude-opus-4-6 via Model Serving
  • Adapter: DatabricksAdapter.fromServingEndpoint()
Reproduction
  1. Create an agent with maxSteps: 10 and multiple tools (e.g., describeTable, executeSql)
  2. Ask a question that triggers 3+ tool calls
  3. Observe that the assistant's text response contains the full answer repeated once per tool-calling round
Ngôn ngữ chính
TypeScript
Star
119
Fork
36
Merge trung bình
4 ngày 16 giờ
Pull request đã merge (30 ngày)
37

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của databricks/appkit

Tất cả issue của databricks/appkit

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.