fix: Capture reasoning in mistral#1863
Conversation
| left: MistralContentPart[] | undefined, | ||
| right: MistralContentPart[], | ||
| ): MistralContentPart[] { | ||
| const merged = [...(left || []).map((part) => structuredClone(part))]; |
There was a problem hiding this comment.
structuredClone here alongside merged.push(structuredClone(part)); is pretty expensive. Can we make that better?
There was a problem hiding this comment.
I find structuredClone here to be already relatively efficient and concise. Unless we lift that we want to be handling cloned objects and instead use the originals (more potential to screw up) I don't quite see an alternative that is much better. Did you have something in mind?
There was a problem hiding this comment.
Yeah I guess that is fair, the objects are pretty small.
I chatted with opus and got something like so, but honestly it's more of a stylistic difference.
function mergeMistralTextSegmentsInPlace(
left: MistralTextContentPart[],
right: MistralTextContentPart[],
): MistralTextContentPart[] {
for (const part of right) {
const lastPart = left[left.length - 1];
if (
lastPart &&
lastPart.type === "text" &&
typeof lastPart.text === "string" &&
typeof part.text === "string"
) {
lastPart.text += part.text;
continue;
}
left.push(part);
}
return left;
}
function mergeMistralContentParts(
left: MistralContentPart[] | undefined,
right: MistralContentPart[],
): MistralContentPart[] {
const merged = left ?? [];
for (const part of right) {
const lastPart = merged[merged.length - 1];
if (
part.type === "text" &&
lastPart?.type === "text" &&
typeof lastPart.text === "string" &&
typeof part.text === "string"
) {
lastPart.text += part.text;
continue;
}
if (
part.type === "thinking" &&
lastPart?.type === "thinking" &&
Array.isArray(lastPart.thinking) &&
Array.isArray(part.thinking)
) {
mergeMistralTextSegmentsInPlace(lastPart.thinking, part.thinking);
continue;
}
merged.push(part);
}
return merged;
}| : []; | ||
|
|
||
| if (thinking.length === 0) { | ||
| return undefined; |
There was a problem hiding this comment.
should we preserve the thinking marker here? And just return an empty thinking array?
There was a problem hiding this comment.
I get your thought but I would just be like "wtf" as a user on braintrust. It's sort of irrelevant to know that there was 0 thinking right? Unless maybe the user wants to use thinking but the model decided not to think. In any case, probably a big edge case - we can return an empty array!
| left: MistralContentPart[] | undefined, | ||
| right: MistralContentPart[], | ||
| ): MistralContentPart[] { | ||
| const merged = [...(left || []).map((part) => structuredClone(part))]; |
There was a problem hiding this comment.
Yeah I guess that is fair, the objects are pretty small.
I chatted with opus and got something like so, but honestly it's more of a stylistic difference.
function mergeMistralTextSegmentsInPlace(
left: MistralTextContentPart[],
right: MistralTextContentPart[],
): MistralTextContentPart[] {
for (const part of right) {
const lastPart = left[left.length - 1];
if (
lastPart &&
lastPart.type === "text" &&
typeof lastPart.text === "string" &&
typeof part.text === "string"
) {
lastPart.text += part.text;
continue;
}
left.push(part);
}
return left;
}
function mergeMistralContentParts(
left: MistralContentPart[] | undefined,
right: MistralContentPart[],
): MistralContentPart[] {
const merged = left ?? [];
for (const part of right) {
const lastPart = merged[merged.length - 1];
if (
part.type === "text" &&
lastPart?.type === "text" &&
typeof lastPart.text === "string" &&
typeof part.text === "string"
) {
lastPart.text += part.text;
continue;
}
if (
part.type === "thinking" &&
lastPart?.type === "thinking" &&
Array.isArray(lastPart.thinking) &&
Array.isArray(part.thinking)
) {
mergeMistralTextSegmentsInPlace(lastPart.thinking, part.thinking);
continue;
}
merged.push(part);
}
return merged;
}
Fixes #1857