Spaces:
Sleeping
Sleeping
/** | |
* Calls the given Gemini model with the given image and/or text | |
* parts, streaming output (as a generator function). | |
*/ | |
export async function* streamGemini({ | |
model = 'gemini-pro', // use 'gemini-pro' for text -> text | |
contents = [], | |
} = {}) { | |
// Send the prompt to the Python backend | |
// Call API defined in main.py | |
let response = await fetch("/api/generate", { | |
method: "POST", | |
headers: { "content-type": "application/json" }, | |
body: JSON.stringify({ model, contents }) | |
}); | |
yield* streamResponseChunks(response); | |
} | |
/** | |
* A helper that streams text output chunks from a fetch() response. | |
*/ | |
async function* streamResponseChunks(response) { | |
let buffer = ''; | |
const CHUNK_SEPARATOR = '\n\n'; | |
let processBuffer = async function* (streamDone = false) { | |
while (true) { | |
let flush = false; | |
let chunkSeparatorIndex = buffer.indexOf(CHUNK_SEPARATOR); | |
if (streamDone && chunkSeparatorIndex < 0) { | |
flush = true; | |
chunkSeparatorIndex = buffer.length; | |
} | |
if (chunkSeparatorIndex < 0) { | |
break; | |
} | |
let chunk = buffer.substring(0, chunkSeparatorIndex); | |
buffer = buffer.substring(chunkSeparatorIndex + CHUNK_SEPARATOR.length); | |
chunk = chunk.replace(/^data:\s*/, '').trim(); | |
if (!chunk) { | |
if (flush) break; | |
continue; | |
} | |
let { error, text } = JSON.parse(chunk); | |
if (error) { | |
console.error(error); | |
throw new Error(error?.message || JSON.stringify(error)); | |
} | |
yield text; | |
if (flush) break; | |
} | |
}; | |
const reader = response.body.getReader(); | |
try { | |
while (true) { | |
const { done, value } = await reader.read() | |
if (done) break; | |
buffer += new TextDecoder().decode(value); | |
console.log(new TextDecoder().decode(value)); | |
yield* processBuffer(); | |
} | |
} finally { | |
reader.releaseLock(); | |
} | |
yield* processBuffer(true); | |
} | |