Skip to content

Commit

Permalink
Merge pull request #347 from cofacts/ai-reply
Browse files Browse the repository at this point in the history
Implement AI reply
  • Loading branch information
MrOrz authored Apr 1, 2023
2 parents 9a40a19 + ffd54d6 commit 8e1928e
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/webhook/handlers/__fixtures__/choosingArticle.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ export const noReplies = {
data: {
GetArticle: {
text: '老司機車裡總備一塊香皂,知道內情的新手默默也準備了一塊',
articleType: 'TEXT',
replyCount: 0,
articleReplies: [],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,36 @@ Object {
"type": "flex",
},
Object {
"altText": "In the meantime, you can:",
"altText": "這篇文章尚待查核中,請先不要相信這篇文章
以下是機器人初步分析此篇訊息的結果,希望能帶給你一些想法。",
"contents": Object {
"body": Object {
"contents": Array [
Object {
"text": "In the meantime, you can:",
"text": "這篇文章尚待查核中,請先不要相信這篇文章
以下是機器人初步分析此篇訊息的結果,希望能帶給你一些想法。",
"type": "text",
"wrap": true,
},
],
"layout": "vertical",
"type": "box",
},
"type": "bubble",
},
"type": "flex",
},
Object {
"text": "Hello from ChatGPT",
"type": "text",
},
Object {
"altText": "讀完以上機器人的自動分析後,您可以:",
"contents": Object {
"body": Object {
"contents": Array [
Object {
"text": "讀完以上機器人的自動分析後,您可以:",
"type": "text",
"wrap": true,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1763,8 +1763,7 @@ Don’t trust the message just yet!",
"body": Object {
"contents": Array [
Object {
"text": "This message has already published on Cofacts, and will soon be fact-checked by volunteers.
Dont trust the message just yet!",
"text": "此訊息已經被收錄至 Cofacts 有待好心人來查證。",
"type": "text",
"wrap": true,
},
Expand All @@ -1786,12 +1785,36 @@ Don’t trust the message just yet!",
"type": "flex",
},
Object {
"altText": "In the meantime, you can:",
"altText": "這篇文章尚待查核,請先不要相信這篇文章
以下是機器人初步分析此篇訊息的結果,希望能帶給你一些想法。",
"contents": Object {
"body": Object {
"contents": Array [
Object {
"text": "這篇文章尚待查核,請先不要相信這篇文章
以下是機器人初步分析此篇訊息的結果,希望能帶給你一些想法。",
"type": "text",
"wrap": true,
},
],
"layout": "vertical",
"type": "box",
},
"type": "bubble",
},
"type": "flex",
},
Object {
"text": "Hello from ChatGPT",
"type": "text",
},
Object {
"altText": "讀完以上機器人的自動分析後,您可以:",
"contents": Object {
"body": Object {
"contents": Array [
Object {
"text": "In the meantime, you can:",
"text": "讀完以上機器人的自動分析後,您可以:",
"type": "text",
"wrap": true,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ it('should submit article if user agrees to submit', async () => {

MockDate.set('2020-01-02');
gql.__push({ data: { CreateArticle: { id: 'new-article-id' } } });
gql.__push({ data: { CreateAIReply: { text: 'Hello from ChatGPT' } } });
const result = await askingArticleSubmissionConsent(params);
MockDate.reset();
expect(gql.__finished()).toBe(true);
Expand Down Expand Up @@ -168,6 +169,7 @@ it('should create a UserArticleLink when creating a Article', async () => {

MockDate.set('2020-01-01');
gql.__push({ data: { CreateArticle: { id: 'new-article-id' } } });
gql.__push({ data: { CreateAIReply: { text: 'Hello from ChatGPT' } } });
await askingArticleSubmissionConsent(params);
MockDate.reset();

Expand All @@ -190,14 +192,15 @@ it('should ask user to turn on notification settings if they did not turn it on
};

gql.__push({ data: { CreateArticle: { id: 'new-article-id' } } });
gql.__push({ data: { CreateAIReply: { text: 'Hello from ChatGPT' } } });
process.env.NOTIFY_METHOD = 'LINE_NOTIFY';
await UserSettings.setAllowNewReplyUpdate(userId, false);

MockDate.set('2020-01-01');
const results = await askingArticleSubmissionConsent(params);
MockDate.reset();

expect(results.replies[2].contents.contents).toMatchSnapshot();
expect(results.replies[4].contents.contents).toMatchSnapshot();

delete process.env.NOTIFY_METHOD;
await UserSettings.setAllowNewReplyUpdate(userId, true);
Expand Down
1 change: 1 addition & 0 deletions src/webhook/handlers/__tests__/choosingArticle.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ it('should select article and have OPINIONATED and NOT_ARTICLE replies', async (

it('should select article with no replies', async () => {
gql.__push(apiGetArticleResult.noReplies);
gql.__push({ data: { CreateAIReply: { text: 'Hello from ChatGPT' } } });
gql.__push(apiGetArticleResult.createOrUpdateReplyRequest);

const params = {
Expand Down
40 changes: 35 additions & 5 deletions src/webhook/handlers/askingArticleSubmissionConsent.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
createArticleShareBubble,
createNotificationSettingsBubble,
getLineContentProxyURL,
createAIReply,
} from './utils';
import UserSettings from 'src/database/models/userSettings';
import UserArticleLink from 'src/database/models/userArticleLink';
Expand All @@ -36,8 +37,9 @@ export default async function askingArticleSubmissionConsent(params) {

case POSTBACK_YES: {
visitor.event({ ec: 'Article', ea: 'Create', el: 'Yes' });
const isTextArticle = data.searchedText && !data.messageId;
let article;
if (data.searchedText && !data.messageId) {
if (isTextArticle) {
const result = await gql`
mutation ($text: String!) {
CreateArticle(text: $text, reference: { type: LINE }) {
Expand All @@ -46,7 +48,12 @@ export default async function askingArticleSubmissionConsent(params) {
}
`({ text: data.searchedText }, { userId });
article = result.data.CreateArticle;
} else if (data.messageId) {
} else {
if (!data.messageId) {
// Should not be here
throw new Error('No message ID found, cannot submit message.');
}

const proxyUrl = getLineContentProxyURL(data.messageId);
const result = await gql`
mutation ($mediaUrl: String!, $articleType: ArticleTypeEnum!) {
Expand Down Expand Up @@ -79,6 +86,31 @@ export default async function askingArticleSubmissionConsent(params) {
userId
);

let maybeAIReplies = [
createTextMessage({
text: t`In the meantime, you can:`,
}),
];

if (isTextArticle) {
const aiReply = await createAIReply(article.id, userId);
/* istanbul ignore else */
if (aiReply) {
maybeAIReplies = [
createTextMessage({
text: '這篇文章尚待查核中,請先不要相信這篇文章。\n以下是機器人初步分析此篇訊息的結果,希望能帶給你一些想法。',
}),
{
type: 'text',
text: aiReply,
},
createTextMessage({
text: '讀完以上機器人的自動分析後,您可以:',
}),
];
}
}

replies = [
{
type: 'flex',
Expand Down Expand Up @@ -107,9 +139,7 @@ export default async function askingArticleSubmissionConsent(params) {
},
},
},
createTextMessage({
text: t`In the meantime, you can:`,
}),
...maybeAIReplies,
{
type: 'flex',
altText: articleCreatedMsg,
Expand Down
37 changes: 34 additions & 3 deletions src/webhook/handlers/choosingArticle.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
createNotificationSettingsBubble,
createArticleShareBubble,
createAskArticleSubmissionConsentReply,
createAIReply,
} from './utils';
import ga from 'src/lib/ga';
import UserSettings from 'src/database/models/userSettings';
Expand Down Expand Up @@ -116,6 +117,7 @@ export default async function choosingArticle(params) {
GetArticle(id: $id) {
text
replyCount
articleType
articleReplies(status: NORMAL) {
reply {
id
Expand Down Expand Up @@ -326,6 +328,33 @@ export default async function choosingArticle(params) {
const { allowNewReplyUpdate } = await UserSettings.findOrInsertByUserId(
userId
);
const isTextArticle = GetArticle.articleType === 'TEXT';

let maybeAIReplies = [
createTextMessage({
text: t`In the meantime, you can:`,
}),
];

if (isTextArticle) {
const aiReply = await createAIReply(selectedArticleId, userId);
/* istanbul ignore else */
if (aiReply) {
maybeAIReplies = [
createTextMessage({
text: '這篇文章尚待查核,請先不要相信這篇文章。\n以下是機器人初步分析此篇訊息的結果,希望能帶給你一些想法。',
}),
{
type: 'text',
text: aiReply,
},
createTextMessage({
text: '讀完以上機器人的自動分析後,您可以:',
}),
];
}
}

replies = [
{
type: 'flex',
Expand All @@ -340,8 +369,10 @@ Don’t trust the message just yet!`,
{
type: 'text',
wrap: true,
text: t`This message has already published on Cofacts, and will soon be fact-checked by volunteers.
Don’t trust the message just yet!`,
text: isTextArticle
? '此訊息已經被收錄至 Cofacts 有待好心人來查證。'
: t`This message has already published on Cofacts, and will soon be fact-checked by volunteers.
Don’t trust the message just yet!`,
},
{
type: 'button',
Expand All @@ -356,7 +387,7 @@ Don’t trust the message just yet!`,
},
},
},
createTextMessage({ text: t`In the meantime, you can:` }),
...maybeAIReplies,
{
type: 'flex',
altText: t`Provide more detail`,
Expand Down
13 changes: 13 additions & 0 deletions src/webhook/handlers/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { t, msgid, ngettext } from 'ttag';
import GraphemeSplitter from 'grapheme-splitter';
import gql from 'src/lib/gql';
import { getArticleURL, createTypeWords } from 'src/lib/sharedUtils';
import { sign } from 'src/lib/jwt';

Expand Down Expand Up @@ -487,6 +488,18 @@ export function createReplyMessages(reply, article, selectedArticleId) {
];
}

export async function createAIReply(articleId, userId) {
return (
await gql`
mutation ($articleId: String!) {
CreateAIReply(articleId: $articleId) {
text
}
}
`({ articleId }, { userId })
).data.CreateAIReply.text;
}

/**
* @param {object} reply `Reply` type from rumors-api
* @param {object} article `Article` type from rumors-api
Expand Down

0 comments on commit 8e1928e

Please sign in to comment.