diff --git a/js/api/openai_responses.js b/js/api/openai_responses.js index f84c0f4e..f4f4977a 100644 --- a/js/api/openai_responses.js +++ b/js/api/openai_responses.js @@ -27,13 +27,13 @@ export class OpenAI { stream = false; store = false; - constructor({ + constructor( apiKey = '', model = '', developer_messages = '', stream = false, store = false - } = {}) { + ) { this.apiKey = apiKey; this.model = model; this.developer_messages = developer_messages; @@ -78,14 +78,20 @@ export class OpenAI { } } - fetchResponse = async (messages, maxTokens = 0) => { + fetchResponse = async (messages, maxTokens = 0, previous_response_id = null) => { + + const input = messages.map(msg => ({ + role: msg.role, + content: [{ type: "input_text", text: msg.content }] + })); let request_body = { model: this.model, - input: messages, + input: input, stream: this.stream, store: this.store, - ...(maxTokens > 0 ? { 'max_completion_tokens': parseInt(maxTokens) } : {}) + ...(maxTokens > 0 ? { 'max_output_tokens': parseInt(maxTokens) } : {}), + ...(previous_response_id && this.store ? { 'previous_response_id': previous_response_id } : {}) } if(this.developer_messages !== ''){ diff --git a/js/workers/model-worker-openai_responses.js b/js/workers/model-worker-openai_responses.js index 2e58e08b..cb1562d5 100644 --- a/js/workers/model-worker-openai_responses.js +++ b/js/workers/model-worker-openai_responses.js @@ -29,11 +29,11 @@ let openai = null; let stopStreaming = false; let i18nStrings = null; let do_debug = false; -let taLog = null +let taLog = null; let conversationHistory = []; let assistantResponseAccumulator = ''; -let previous_response_id = -1; +let previous_response_id = null; self.onmessage = async function(event) { if (event.data.type === 'init') { @@ -43,10 +43,19 @@ self.onmessage = async function(event) { do_debug = event.data.do_debug; i18nStrings = event.data.i18nStrings; taLog = new taLogger('model-worker-openai_responses', do_debug); + previous_response_id = null; } else if (event.data.type === 'chatMessage') { conversationHistory.push({ role: 'user', content: event.data.message }); - const response = await openai.fetchResponse(conversationHistory); //4096); + let messagesToSend = conversationHistory; + if (previous_response_id) { + messagesToSend = [conversationHistory[conversationHistory.length - 1]]; + taLog.log("previous_response_id: " + previous_response_id); + } else { + taLog.log("no previous_response_id"); + } + + const response = await openai.fetchResponse(messagesToSend, 0, previous_response_id); postMessage({ type: 'messageSent' }); if (!response.ok) { @@ -97,24 +106,33 @@ self.onmessage = async function(event) { let parsedLines = []; try{ parsedLines = lines + .map((line) => line.trim()) + .filter((line) => line.startsWith("data:")) .map((line) => line.replace(/^data: /, "").trim()) // Remove the "data: " prefix .filter((line) => line !== "" && line !== "[DONE]") // Remove empty lines and "[DONE]" // .map((line) => JSON.parse(line)); // Parse the JSON string .map((line) => { - taLog.log("line: " + JSON.stringify(line)); - return JSON.parse(line); - }); + try { + taLog.log("line: " + JSON.stringify(line)); + return JSON.parse(line); + } catch (e) { + taLog.warn("JSON parse warning, skipped line: " + line + " - " + e.message); + return null; + } + }) + .filter((parsed) => parsed !== null); }catch(e){ taLog.error("Error parsing lines: " + e); } for (const parsedLine of parsedLines) { - console.log(">>>>>>>>>> parsedLine: " + JSON.stringify(parsedLine)); - const { content } = parsedLine; - // Update the UI with the new content - if (content) { - assistantResponseAccumulator += content; - postMessage({ type: 'newToken', payload: { token: content } }); + if (parsedLine.type === 'response.created' && parsedLine.response && parsedLine.response.id){ + previous_response_id = parsedLine.response.id; + } else if (parsedLine.type === 'response.output_text.delta' && parsedLine.delta) { + assistantResponseAccumulator += parsedLine.delta; + postMessage({ type: 'newToken', payload: { token: parsedLine.delta } }); + // } else if (parsedLine.type === 'response.completed' && parsedLine.response && parsedLine.response.id) { + // previous_response_id = parsedLine.response.id; } } }