My Latest Contribution to ChatCraft
Published: 2023-12-12 02:44:23

## Latest Changes

So, to pick up where I left off from my previous post, I was able to stick to my plan of using the `Strategy Pattern` within the functional component paradigm structure instead of class component paradigm. Here are the changes I made to the code base to reflect my plan: 
* I created an `interface` function which defines the structure for my response handling functions:
```typescript
interface ResponseHandlerStrategy {
  (response: any): Promise<any>;
}
``` 
* I created a `responseHandler` which is in charge of selecting the right response handler function based on the boolean `streaming` flag:
```typescript
  const responseHandler: ResponseHandlerStrategy = streaming
    ? handleStreamingResponse
    : handleNonStreamingResponse;
```
* I created 2 different implementations for handling the responses. One is for handling an streaming response and the other is for handling a non-streaming response:
```typescript
  const handleStreamingResponse: ResponseHandlerStrategy = async (
    streamResponse: Stream<ChatCompletionChunk>
  ) => {
    for await (const streamChunk of streamResponse) {
      const parsedData = parseOpenAIChunkResponse(streamChunk);
      await streamOpenAIResponse(
        parsedData.token,
        parsedData.functionName,
        parsedData.functionArgs
      );
    }

    const content = buffer.join("");
    return handleOpenAIResponse(content, functionName, functionArgs);
  };
```
```typescript
  const handleNonStreamingResponse: ResponseHandlerStrategy = async (response: ChatCompletion) => {
    const { content, functionName, functionArgs } = parseOpenAIResponse(response);
    return handleOpenAIResponse(content, functionName, functionArgs);
  };
``` 
* Implemented the above functions in the main `chatWithLLM` function and modified the code base to support these functions within a single code path:
```typescript
[...]
 const responsePromise = openai.chat.completions
    .create(
      chatCompletionParams as OpenAI.Chat.ChatCompletionCreateParamsStreaming,
      chatCompletionReqOptions
    )
    .then(async (response) => {
      return responseHandler(response);
    })
    .catch((err) => {
      return handleError(err);
    })
    .finally(() => {
      removeEventListener("keydown", handleCancel);
    });

  return {
    promise: responsePromise,
    cancel,
    pause,
    resume,
    togglePause,
  };
```
* Ran the application to make sure that these new functions were working correctly and didn't break the overall functionality of the program.

* Formatted the code with Prettier via VSCode, committed my changes, and created a [PR](https://github.com/tarasglek/chatcraft.org/pull/304).

## What I Leveraged
* I used the OpenAI API [`chat`](https://platform.openai.com/docs/api-reference/chat) documentation to familiarize myself with and understand different chat objects, types of responses, and the different return types.
* I researched the `strategy pattern` and its application in Typescript from different sources online.
* I used the comments and the feedbacks provided in a previous [PR](https://github.com/tarasglek/chatcraft.org/pull/220#discussion_r1299371774) for the project that were related to the issue I worked on. I used these to understand what was needed for me to do and the overall logic and the structure of the code base.

## Conclusion
At first I was a bit intimidated to contribute to a larger project. However, I am happy that I jumped into it with a plan which guided me throughout my contribution. I am happy that my original plan worked out, even though I had to change my approach to fit the functional structure of the code-base. I am glad that I got to work on a project which used OpenAI API so I could learn more about it. Also, I am happy that I got to use a design pattern that I had learned theoretically but never had the chance to apply it in Typescript. I am still waiting for my PR to be reviewed, and based on the feedback, if there are any changes needed, I will make sure to address them with appropriate adjustments.