fix(DeepSeekAI): keep nameless arg fragments when grouping tool calls
The previous grouping pre-filtered tool-call updates on FunctionName
before grouping by index. In DeepSeek streaming only the FIRST fragment
of a call carries the name/id; the argument text arrives in later
fragments with FunctionName == null. The filter dropped them, so every
tool call got empty FunctionArgs (get_editor_state(), get_node() ->
'node_id is required').
Group ALL updates by Index first, then pick the first group that
contains a named fragment and concatenate every argument fragment in
that group. Verified via OpenPencil integration test: get_node now
carries {"node_id": "10"} intact instead of being empty or joined
across parallel calls.
This commit is contained in:
parent
9fe969a47c
commit
aa132b1419
|
|
@ -284,20 +284,28 @@ public class ChatCompletionProvider : IChatCompletion
|
|||
|
||||
if (choice.FinishReason == ChatFinishReason.ToolCalls || choice.FinishReason == ChatFinishReason.FunctionCall)
|
||||
{
|
||||
// The model may emit several tool calls in one response. The OpenAI SDK streams each
|
||||
// call's arguments as interleaved fragments per call index, so we must accumulate them
|
||||
// PER CALL (grouped by index), not concatenate every fragment of every call together
|
||||
// (that would corrupt arguments, e.g. get_node({"node_id": "10"}{"maxDepth": 2})).
|
||||
var grouped = toolCalls
|
||||
.Where(x => !string.IsNullOrEmpty(x.FunctionName))
|
||||
// The model may emit several tool calls in one response. The OpenAI SDK streams
|
||||
// arguments as interleaved fragments PER CALL INDEX: the first fragment of a call
|
||||
// carries the name/id and an empty arguments payload, later fragments carry only
|
||||
// the argument text (FunctionName is null on them). We must accumulate fragments
|
||||
// grouped by Index and must NOT pre-filter on FunctionName (that would drop the
|
||||
// argument-carrying fragments and yield empty FunctionArgs).
|
||||
//
|
||||
// Old bug: string.Join over ALL fragments of ALL calls produced corrupted
|
||||
// arguments (get_node({"node_id": "10"}{"maxDepth": 2})), which made every
|
||||
// tool call fail with e.g. "node_id is required".
|
||||
var groups = toolCalls
|
||||
.GroupBy(x => x.Index)
|
||||
.OrderBy(g => g.Key)
|
||||
.ToList();
|
||||
|
||||
var functionName = grouped.Count > 0 ? grouped[0].First().FunctionName : null;
|
||||
var toolCallId = grouped.Count > 0 ? grouped[0].First().ToolCallId : null;
|
||||
var functionArgument = grouped.Count > 0
|
||||
? string.Concat(grouped[0].Where(x => x.FunctionArgumentsUpdate != null).Select(x => x.FunctionArgumentsUpdate.ToString()))
|
||||
var namedGroup = groups.FirstOrDefault(g => g.Any(x => !string.IsNullOrEmpty(x.FunctionName)));
|
||||
var namedUpdate = namedGroup?.FirstOrDefault(x => !string.IsNullOrEmpty(x.FunctionName));
|
||||
|
||||
var functionName = namedUpdate?.FunctionName;
|
||||
var toolCallId = namedUpdate?.ToolCallId;
|
||||
var functionArgument = namedGroup != null
|
||||
? string.Concat(namedGroup.Where(x => x.FunctionArgumentsUpdate != null).Select(x => x.FunctionArgumentsUpdate.ToString()))
|
||||
: string.Empty;
|
||||
|
||||
#if DEBUG
|
||||
|
|
|
|||
Loading…
Reference in a new issue