mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-29 19:12:27 +08:00
well this at least allows for streaming responses when no tool calls are made
This commit is contained in:
parent
263c869091
commit
d1edf59f97
@ -87,9 +87,13 @@ export async function setupStreamingResponse(
|
||||
// Handle content updates
|
||||
if (message.content) {
|
||||
receivedAnyContent = true;
|
||||
|
||||
console.log(`[${responseId}] Received content chunk of length ${message.content.length}, preview: "${message.content.substring(0, 50)}${message.content.length > 50 ? '...' : ''}"`);
|
||||
|
||||
// Add to our accumulated response
|
||||
assistantResponse += message.content;
|
||||
|
||||
// Update the UI immediately
|
||||
// Update the UI immediately with each chunk
|
||||
onContentUpdate(assistantResponse);
|
||||
|
||||
// Reset timeout since we got content
|
||||
|
@ -430,13 +430,27 @@ export class OllamaService extends BaseAIService {
|
||||
|
||||
// Call the callback with the current chunk content
|
||||
if (opts.streamCallback) {
|
||||
// For chunks with content, send the content directly
|
||||
if (chunk.message?.content) {
|
||||
log.info(`Sending direct chunk #${chunkCount} with content: "${chunk.message.content.substring(0, 50)}${chunk.message.content.length > 50 ? '...' : ''}"`);
|
||||
|
||||
await StreamProcessor.sendChunkToCallback(
|
||||
opts.streamCallback,
|
||||
chunk.message?.content || '',
|
||||
false, // Never mark as done during processing
|
||||
chunk.message.content,
|
||||
!!chunk.done, // Mark as done if done flag is set
|
||||
chunk,
|
||||
chunkCount
|
||||
);
|
||||
} else if (chunk.done) {
|
||||
// Send empty done message for final chunk with no content
|
||||
await StreamProcessor.sendChunkToCallback(
|
||||
opts.streamCallback,
|
||||
'',
|
||||
true,
|
||||
chunk,
|
||||
chunkCount
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// If this is the done chunk, log it
|
||||
@ -446,7 +460,9 @@ export class OllamaService extends BaseAIService {
|
||||
}
|
||||
|
||||
// Send one final callback with done=true after all chunks have been processed
|
||||
if (opts.streamCallback) {
|
||||
// Only send this if the last chunk didn't already have done=true
|
||||
if (opts.streamCallback && (!finalChunk || !finalChunk.done)) {
|
||||
log.info(`Sending explicit final callback with done=true flag after all chunks processed`);
|
||||
await StreamProcessor.sendFinalCallback(opts.streamCallback, completeText);
|
||||
}
|
||||
|
||||
|
@ -40,9 +40,9 @@ export class StreamProcessor {
|
||||
let textToAdd = '';
|
||||
let logged = false;
|
||||
|
||||
// Log first chunk and periodic updates
|
||||
if (chunkCount === 1 || chunkCount % 10 === 0) {
|
||||
log.info(`Processing ${options.providerName} stream chunk #${chunkCount}, done=${!!chunk.done}, has content=${!!chunk.message?.content}`);
|
||||
// Enhanced logging for content chunks and completion status
|
||||
if (chunkCount === 1 || chunkCount % 10 === 0 || chunk.done) {
|
||||
log.info(`Processing ${options.providerName} stream chunk #${chunkCount}, done=${!!chunk.done}, has content=${!!chunk.message?.content}, content length=${chunk.message?.content?.length || 0}`);
|
||||
logged = true;
|
||||
}
|
||||
|
||||
@ -52,10 +52,19 @@ export class StreamProcessor {
|
||||
const newCompleteText = completeText + textToAdd;
|
||||
|
||||
if (chunkCount === 1) {
|
||||
log.info(`First content chunk: "${textToAdd.substring(0, 50)}${textToAdd.length > 50 ? '...' : ''}"`);
|
||||
// Log the first chunk more verbosely for debugging
|
||||
log.info(`First content chunk [${chunk.message.content.length} chars]: "${textToAdd.substring(0, 100)}${textToAdd.length > 100 ? '...' : ''}"`);
|
||||
}
|
||||
|
||||
// For final chunks with done=true, log more information
|
||||
if (chunk.done) {
|
||||
log.info(`Final content chunk received with done=true flag. Length: ${chunk.message.content.length}`);
|
||||
}
|
||||
|
||||
return { completeText: newCompleteText, logged };
|
||||
} else if (chunk.done) {
|
||||
// If it's the final chunk with no content, log this case
|
||||
log.info(`Empty final chunk received with done=true flag`);
|
||||
}
|
||||
|
||||
return { completeText, logged };
|
||||
@ -72,7 +81,15 @@ export class StreamProcessor {
|
||||
chunkNumber: number
|
||||
): Promise<void> {
|
||||
try {
|
||||
const result = callback(content || '', done, chunk);
|
||||
// Log all done=true callbacks and first chunk for debugging
|
||||
if (done || chunkNumber === 1) {
|
||||
log.info(`Sending chunk to callback: chunkNumber=${chunkNumber}, contentLength=${content?.length || 0}, done=${done}`);
|
||||
}
|
||||
|
||||
// Always make sure we have a string for content
|
||||
const safeContent = content || '';
|
||||
|
||||
const result = callback(safeContent, done, chunk);
|
||||
// Handle both Promise and void return types
|
||||
if (result instanceof Promise) {
|
||||
await result;
|
||||
@ -81,6 +98,10 @@ export class StreamProcessor {
|
||||
if (chunkNumber === 1) {
|
||||
log.info(`Successfully called streamCallback with first chunk`);
|
||||
}
|
||||
|
||||
if (done) {
|
||||
log.info(`Successfully called streamCallback with done=true flag`);
|
||||
}
|
||||
} catch (callbackError) {
|
||||
log.error(`Error in streamCallback: ${callbackError}`);
|
||||
}
|
||||
@ -94,12 +115,18 @@ export class StreamProcessor {
|
||||
completeText: string
|
||||
): Promise<void> {
|
||||
try {
|
||||
log.info(`Sending final done=true callback after processing all chunks`);
|
||||
const result = callback('', true, { done: true });
|
||||
log.info(`Sending explicit final done=true callback after processing all chunks. Complete text length: ${completeText?.length || 0}`);
|
||||
|
||||
// Pass the complete text instead of empty string for better UX
|
||||
// The client will know it's done based on the done=true flag
|
||||
const result = callback(completeText || '', true, { done: true, complete: true });
|
||||
|
||||
// Handle both Promise and void return types
|
||||
if (result instanceof Promise) {
|
||||
await result;
|
||||
}
|
||||
|
||||
log.info(`Final callback sent successfully with done=true flag`);
|
||||
} catch (finalCallbackError) {
|
||||
log.error(`Error in final streamCallback: ${finalCallbackError}`);
|
||||
}
|
||||
|
@ -1163,18 +1163,22 @@ class RestChatService {
|
||||
if (chunk.text) {
|
||||
messageContent += chunk.text;
|
||||
|
||||
// Send the chunk content via WebSocket
|
||||
// Enhanced logging for each chunk
|
||||
log.info(`Received stream chunk from ${service.getName()} with ${chunk.text.length} chars of text, done=${!!chunk.done}`);
|
||||
|
||||
// Send each individual chunk via WebSocket as it arrives
|
||||
wsService.sendMessageToAllClients({
|
||||
type: 'llm-stream',
|
||||
sessionId,
|
||||
content: chunk.text,
|
||||
done: !!chunk.done, // Include done flag with each chunk
|
||||
// Include any raw data from the provider that might contain thinking/tool info
|
||||
...(chunk.raw ? { raw: chunk.raw } : {})
|
||||
} as LLMStreamMessage);
|
||||
|
||||
// Log the first chunk (useful for debugging)
|
||||
if (messageContent.length === chunk.text.length) {
|
||||
log.info(`First stream chunk received from ${service.getName()}`);
|
||||
log.info(`First stream chunk received from ${service.getName()}: "${chunk.text.substring(0, 50)}${chunk.text.length > 50 ? '...' : ''}"`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1198,15 +1202,23 @@ class RestChatService {
|
||||
|
||||
// Signal completion when done
|
||||
if (chunk.done) {
|
||||
log.info(`Stream completed from ${service.getName()}`);
|
||||
log.info(`Stream completed from ${service.getName()}, total content: ${messageContent.length} chars`);
|
||||
|
||||
// Send the final message with both content and done flag together
|
||||
// Only send final done message if it wasn't already sent with content
|
||||
// This ensures we don't duplicate the content but still mark completion
|
||||
if (!chunk.text) {
|
||||
// Send final message with both content and done flag together
|
||||
wsService.sendMessageToAllClients({
|
||||
type: 'llm-stream',
|
||||
sessionId,
|
||||
content: messageContent, // Send the accumulated content
|
||||
done: true
|
||||
} as LLMStreamMessage);
|
||||
|
||||
log.info(`Sent explicit final completion message with accumulated content`);
|
||||
} else {
|
||||
log.info(`Final done flag was already sent with content chunk, no need for extra message`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user