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:
interface ResponseHandlerStrategy {
(response: any): Promise<any>;
}
- I created a
responseHandler
which is in charge of selecting the right response handler function based on the booleanstreaming
flag:
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:
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);
};
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:
[...]
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.
What I Leveraged
- I used the OpenAI API
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 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.
Top comments (0)