Skip to content

Instantly share code, notes, and snippets.

@tikikun
Created May 24, 2023 02:20
Show Gist options
  • Save tikikun/028065bcd6c460352e44f76c81ff152b to your computer and use it in GitHub Desktop.
Save tikikun/028065bcd6c460352e44f76c81ff152b to your computer and use it in GitHub Desktop.

Revisions

  1. tikikun created this gist May 24, 2023.
    86 changes: 86 additions & 0 deletions workingSSE.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,86 @@
    import message from './LLM'

    const streamToComponent = async (
    chatContent: message[],
    setTargetText: React.Dispatch<React.SetStateAction<message[]>>
    ) => {
    const url = "https://api.openai.com/v1/chat/completions";

    // set initial value for the chat
    setTargetText([...chatContent, { role: "", content: "" }]);

    const body = JSON.stringify({
    messages: chatContent,
    stream: true,
    model: "gpt-3.5-turbo",
    max_tokens: 2000,
    });

    try {
    const response = await fetch(url, {
    method: "POST",
    mode: "cors",
    headers: {
    "Content-Type": "application/json",
    Accept: "text/event-stream",
    Authorization:
    "Access-Control-Allow-Origin": "*",
    },
    body,
    });

    const reader = response.body!.getReader();
    const decoder = new TextDecoder();
    while (true) {
    // Read a chunk from the stream
    const { value, done } = await reader.read();

    // If the stream is done, break the loop
    if (done) {
    break;
    }
    const string_payload: string = decoder.decode(value, { stream: true });
    const list_payload: string[] = string_payload
    .split("\n")
    .filter((line) => line.trim() !== "");

    for (const line of list_payload) {
    const message = line.replace(/^data: /, "");
    if (message.startsWith("[DONE]")) {
    return; // Stream finished
    }
    try {
    const parsed = JSON.parse(message);
    const result: any = parsed.choices[0].delta;
    //console.log(result);
    if ("role" in result) {
    setTargetText((targetText: message[]) => [
    ...targetText.slice(0, -1),
    {
    ...targetText[targetText.length - 1],
    role: result.role.toString(),
    },
    ]);
    }
    if ("content" in result) {
    setTargetText((targetText: message[]) => [
    ...targetText.slice(0, -1),
    {
    ...targetText[targetText.length - 1],
    content:
    targetText[targetText.length - 1].content +
    result.content.toString(),
    },
    ]);
    }
    } catch (error) {
    console.error("Could not JSON parse stream message", message, error);
    }
    }
    }
    } catch (error) {
    console.error(error);
    }
    };

    export default streamToComponent;