Skip to content

Commit 1ff046c

Browse files
committed
Fix real-world streaming
1 parent 44bfe64 commit 1ff046c

File tree

5 files changed

+41
-18
lines changed

5 files changed

+41
-18
lines changed

packages/ai-bot/lib/responder.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ export class Responder {
7575
) {
7676
const toolCallsSnapshot = snapshot.choices[0].message.tool_calls;
7777
if (toolCallsSnapshot?.length) {
78-
if (
79-
JSON.stringify(this.toolCalls) !== JSON.stringify(toolCallsSnapshot)
80-
) {
78+
let latestToolCallsJson = JSON.stringify(toolCallsSnapshot);
79+
if (this.toolCallsJson !== latestToolCallsJson) {
8180
this.toolCalls = toolCallsSnapshot;
81+
this.toolCallsJson = latestToolCallsJson;
8282
await this.sendMessageEventWithThrottling();
8383
}
8484
}
@@ -134,7 +134,14 @@ export class Responder {
134134
result['name'] = f.name;
135135
}
136136
if (f.arguments) {
137-
result['arguments'] = JSON.parse(f.arguments);
137+
try {
138+
result['arguments'] = JSON.parse(f.arguments);
139+
} catch (error) {
140+
// If the arguments are not valid JSON, we'll just return an empty object
141+
// This will happen during streaming, when the tool call is not yet complete
142+
// and the arguments are not yet available
143+
result['arguments'] = {};
144+
}
138145
}
139146
return result;
140147
}
@@ -162,6 +169,10 @@ export class Responder {
162169
}
163170

164171
async finalize() {
172+
if (!this.isStreamingFinished) {
173+
this.isStreamingFinished = true;
174+
await this.sendMessageEventWithThrottling();
175+
}
165176
await this.flush();
166177
}
167178
}

packages/ai-bot/main.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ Common issues are:
212212
let eventList = (initial!.messages?.chunk ||
213213
[]) as DiscreteMatrixEvent[];
214214
try {
215-
promptParts = getPromptParts(eventList, aiBotUserId);
215+
promptParts = await getPromptParts(eventList, aiBotUserId);
216216
if (!promptParts.shouldRespond) {
217217
return;
218218
}

packages/ai-bot/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"@types/stream-json": "^1.7.3",
1212
"lodash": "~4.17.21",
1313
"matrix-js-sdk": "^31.0.0",
14-
"openai": "4.47.1",
14+
"openai": "4.86.1",
1515
"qunit": "^2.18.0",
1616
"stream-chain": "^2.2.5",
1717
"stream-json": "^1.8.0",

packages/ai-bot/tests/responding-test.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ module('Responding', (hooks) => {
354354
let sentEvents = fakeMatrixClient.getSentEvents();
355355
assert.equal(
356356
sentEvents.length,
357-
4,
357+
5,
358358
'Thinking message, and event with content, event with partial tool call, and event with full tool call should be sent',
359359
);
360360
assert.equal(
@@ -424,6 +424,16 @@ module('Responding', (hooks) => {
424424
},
425425
'The replacement event with the tool call event should replace the original message',
426426
);
427+
assert.deepEqual(
428+
sentEvents[3].content.isStreamingFinished,
429+
false,
430+
'The tool call event should not be sent with isStreamingFinished set to true',
431+
);
432+
assert.deepEqual(
433+
sentEvents[4].content.isStreamingFinished,
434+
true,
435+
'The final event should be sent with isStreamingFinished set to true',
436+
);
427437
});
428438

429439
test('Handles multiple tool calls', async () => {

pnpm-lock.yaml

+13-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)