Skip to content

Commit

Permalink
refactor(CreateAIReply): extract AI Response creation and updating to…
Browse files Browse the repository at this point in the history
… util function
  • Loading branch information
MrOrz committed Jul 6, 2023
1 parent 44aeba1 commit 5595aed
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 58 deletions.
83 changes: 25 additions & 58 deletions src/graphql/mutations/CreateAIReply.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import { GraphQLString, GraphQLNonNull } from 'graphql';

import openai from 'util/openai';
import { assertUser } from 'util/user';
import client from 'util/client';
import { AIReply } from 'graphql/models/AIResponse';
import { getAIResponse } from 'graphql/util';
import { getAIResponse, createAIResponse } from 'graphql/util';

const monthFormatter = Intl.DateTimeFormat('zh-TW', {
year: 'numeric',
Expand Down Expand Up @@ -90,32 +89,15 @@ export async function createNewAIReply({
...completionOptions,
};

const newResponse = {
userId: user.id,
appId: user.appId,
const updateAIResponse = createAIResponse({
user,
docId: article.id,
type: 'AI_REPLY',
status: 'LOADING',
request: JSON.stringify(completionRequest),
createdAt: new Date(),
};

// Resolves to loading AI Response.
const newResponseIdPromise = client
.index({
index: 'airesponses',
type: 'doc',
body: newResponse,
})
.then(({ body: { result, _id } }) => {
/* istanbul ignore if */
if (result !== 'created') {
throw new Error(`Cannot create AI reply: ${result}`);
}
return _id;
});
});

const openAIResponsePromise = openai
// Resolves to completed or errored AI response.
const apiResult = await openai
.createChatCompletion(completionRequest)
.then(({ data }) => data)
.catch(error => {
Expand All @@ -127,41 +109,26 @@ export async function createNewAIReply({
return new Error(error);
});

// Resolves to completed or errored AI response.
return Promise.all([openAIResponsePromise, newResponseIdPromise])
.then(([apiResult, aiResponseId]) =>
// Update using aiResponse._id according to apiResult
client.update({
index: 'airesponses',
type: 'doc',
id: aiResponseId,
_source: true,
body: {
doc:
apiResult instanceof Error
? {
status: 'ERROR',
text: apiResult.toString(),
updatedAt: new Date(),
}
: {
status: 'SUCCESS',
text: apiResult.choices[0].message.content,
...(apiResult.usage
? {
usage: {
promptTokens: apiResult.usage.prompt_tokens,
completionTokens: apiResult.usage.completion_tokens,
totalTokens: apiResult.usage.total_tokens,
},
}
: undefined),
updatedAt: new Date(),
return updateAIResponse(
apiResult instanceof Error
? {
status: 'ERROR',
text: apiResult.toString(),
}
: {
status: 'SUCCESS',
text: apiResult.choices[0].message.content,
...(apiResult.usage
? {
usage: {
promptTokens: apiResult.usage.prompt_tokens,
completionTokens: apiResult.usage.completion_tokens,
totalTokens: apiResult.usage.total_tokens,
},
},
})
)
.then(({ body: { _id, get: { _source } } }) => ({ id: _id, ..._source }));
}
: undefined),
}
);
}

export default {
Expand Down
75 changes: 75 additions & 0 deletions src/graphql/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -610,3 +610,78 @@ export async function getAIResponse({ type, docId }) {
// Nothing is found
return null;
}

/**
* Creates a loading AI Response.
* Returns an updater function that can be used to record real AI response.
*
*
* @param {object} loadingResponseBody
* @param {string} loadingResponseBody.request
* @param {string} loadingResponseBody.type
* @param {string} loadingResponseBody.docId
* @param {object} loadingResponseBody.user
*
* @returns {(responseBody) => Promise<AIResponse>} updater function that updates the created AI
* response and returns the updated result
*/
export function createAIResponse({ user, ...loadingResponseBody }) {
const newResponse = {
userId: user.id,
appId: user.appId,
status: 'LOADING',
createdAt: new Date(),
...loadingResponseBody,
};

// Resolves to loading AI Response.
const newResponseIdPromise = client
.index({
index: 'airesponses',
type: 'doc',
body: newResponse,
})
.then(({ body: { result, _id } }) => {
/* istanbul ignore if */
if (result !== 'created') {
throw new Error(`Cannot create AI response: ${result}`);
}
return _id;
});

// Update using aiResponse._id according to apiResult
async function update(responseBody) {
const aiResponseId = await newResponseIdPromise;

const {
body: {
get: { _source },
},
} = await client.update({
index: 'airesponses',
type: 'doc',
id: aiResponseId,
_source: true,
body: {
doc: {
updatedAt: new Date(),
...responseBody,
},
},
});

return {
id: aiResponseId,
..._source,
};
}

return update;
}

/**
*
* @param {*} mediaEntryId
* @param {*} fileUrl
*/
// async function createTranscript(mediaEntryId, fileUrl) {}

0 comments on commit 5595aed

Please sign in to comment.