From bacdecc75aae2ad797ac3dafb347369bfc65b238 Mon Sep 17 00:00:00 2001 From: Nick O'Ferrall Date: Thu, 21 Nov 2024 15:16:07 +0100 Subject: [PATCH 1/3] chore: remove ai template --- codegen.json | 1 - .../components/ActivityLibrary/AISearch.tsx | 97 ------------------- .../ActivityLibrary/ActivityLibrary.tsx | 24 +---- .../GetTemplateSuggestionMutation.ts | 41 -------- .../public/mutations/getTemplateSuggestion.ts | 65 ------------- .../GetTemplateSuggestionPayload.graphql | 4 - .../GetTemplateSuggestionSuccess.graphql | 11 --- .../graphql/public/typeDefs/Mutation.graphql | 10 -- .../types/GetTemplateSuggestionSuccess.ts | 16 --- packages/server/utils/OpenAIServerManager.ts | 44 --------- 10 files changed, 2 insertions(+), 311 deletions(-) delete mode 100644 packages/client/components/ActivityLibrary/AISearch.tsx delete mode 100644 packages/client/mutations/GetTemplateSuggestionMutation.ts delete mode 100644 packages/server/graphql/public/mutations/getTemplateSuggestion.ts delete mode 100644 packages/server/graphql/public/typeDefs/GetTemplateSuggestionPayload.graphql delete mode 100644 packages/server/graphql/public/typeDefs/GetTemplateSuggestionSuccess.graphql delete mode 100644 packages/server/graphql/public/types/GetTemplateSuggestionSuccess.ts diff --git a/codegen.json b/codegen.json index 27ff63a820f..4fe9d14f16d 100644 --- a/codegen.json +++ b/codegen.json @@ -90,7 +90,6 @@ "GcalIntegration": "./types/GcalIntegration#GcalIntegrationSource", "GenerateGroupsSuccess": "./types/GenerateGroupsSuccess#GenerateGroupsSuccessSource", "GenerateInsightSuccess": "./types/GenerateInsightSuccess#GenerateInsightSuccessSource", - "GetTemplateSuggestionSuccess": "./types/GetTemplateSuggestionSuccess#GetTemplateSuggestionSuccessSource", "GitHubIntegration": "../../postgres/queries/getGitHubAuthByUserIdTeamId#GitHubAuth", "GitLabIntegration": "./types/GitLabIntegration#GitLabIntegrationSource", "IntegrationProviderOAuth1": "../../postgres/queries/getIntegrationProvidersByIds#TIntegrationProvider", diff --git a/packages/client/components/ActivityLibrary/AISearch.tsx b/packages/client/components/ActivityLibrary/AISearch.tsx deleted file mode 100644 index 4bb9f9e7cc7..00000000000 --- a/packages/client/components/ActivityLibrary/AISearch.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import * as React from 'react' -import {useState} from 'react' -import {GetTemplateSuggestionMutation$data} from '../../__generated__/GetTemplateSuggestionMutation.graphql' -import useAtmosphere from '../../hooks/useAtmosphere' -import useMutationProps from '../../hooks/useMutationProps' -import GetTemplateSuggestionMutation from '../../mutations/GetTemplateSuggestionMutation' -import LoadingComponent from '../LoadingComponent/LoadingComponent' -import StyledError from '../StyledError' -import ActivityGrid from './ActivityGrid' - -type SuggestedTemplate = - GetTemplateSuggestionMutation$data['getTemplateSuggestion']['suggestedTemplate'] - -const AISearch = () => { - const atmosphere = useAtmosphere() - const {onCompleted, onError, submitMutation, submitting, error} = useMutationProps() - const [suggestedTemplate, setSuggestedTemplate] = useState(null) - const [explanation, setExplanation] = useState('') - const [prompt, setPrompt] = useState('') - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault() - if (!prompt) { - const error = new Error('Please enter a prompt') - onError(error) - return - } - const variables = {prompt} - submitMutation() - GetTemplateSuggestionMutation(atmosphere, variables, { - onError, - onCompleted: (res: GetTemplateSuggestionMutation$data) => { - const {getTemplateSuggestion} = res - if (getTemplateSuggestion?.error) { - const error = new Error(res.getTemplateSuggestion?.error?.message) - onError(error) - } else if (getTemplateSuggestion.explanation && getTemplateSuggestion.suggestedTemplate) { - setSuggestedTemplate(getTemplateSuggestion.suggestedTemplate) - setExplanation(getTemplateSuggestion.explanation) - onCompleted() - } - } - }) - } - - const handlePromptChange = (e: React.ChangeEvent) => { - setPrompt(e.target.value) - } - - return ( - <> -
- - -
-
- {submitting && } - {error?.message && !submitting && ( - {`Despite its best efforts, our AI couldn't find a matching template. Try again?`} - )} - {!submitting && suggestedTemplate && ( - <> -
Our AI's Suggestion
-
-
{explanation}
-
-
- -
- - )} -
- - ) -} - -export default AISearch diff --git a/packages/client/components/ActivityLibrary/ActivityLibrary.tsx b/packages/client/components/ActivityLibrary/ActivityLibrary.tsx index 4c9114c897b..fe283c85aae 100644 --- a/packages/client/components/ActivityLibrary/ActivityLibrary.tsx +++ b/packages/client/components/ActivityLibrary/ActivityLibrary.tsx @@ -24,7 +24,6 @@ import logoMarkPurple from '../../styles/theme/images/brand/mark-color.svg' import SendClientSideEvent from '../../utils/SendClientSideEvent' import IconLabel from '../IconLabel' import LoadingComponent from '../LoadingComponent/LoadingComponent' -import AISearch from './AISearch' import ActivityGrid from './ActivityGrid' import ActivityLibraryEmptyState from './ActivityLibraryEmptyState' import { @@ -117,9 +116,6 @@ const query = graphql` } } } - organizations { - hasAITemplateFlag: featureFlag(featureName: "aiTemplate") - } } } ` @@ -226,8 +222,7 @@ export const ActivityLibrary = (props: Props) => { const {queryRef} = props const data = usePreloadedQuery(query, queryRef) const {viewer} = data - const {availableTemplates, organizations} = viewer - const hasAITemplateFeatureFlag = organizations.some((org) => org.hasAITemplateFlag) + const {availableTemplates} = viewer const [isSearching, setIsSearching] = useState(true) const [templateSearch, refetchTemplateSearch] = useRefetchableFragment< @@ -361,17 +356,7 @@ export const ActivityLibrary = (props: Props) => { Start Activity - {!hasAITemplateFeatureFlag && ( -
- { - onQueryChange(e) - setSearch(e.target.value) - }} - /> -
- )} + { - {hasAITemplateFeatureFlag && ( -
- -
- )} {templatesToRender.length === 0 && !showLoading ? ( = ( - atmosphere, - variables, - {onError, onCompleted} -) => { - return commitMutation(atmosphere, { - mutation, - variables, - onCompleted, - onError - }) -} - -export default GetTemplateSuggestionMutation diff --git a/packages/server/graphql/public/mutations/getTemplateSuggestion.ts b/packages/server/graphql/public/mutations/getTemplateSuggestion.ts deleted file mode 100644 index 0e2267bcf13..00000000000 --- a/packages/server/graphql/public/mutations/getTemplateSuggestion.ts +++ /dev/null @@ -1,65 +0,0 @@ -import {getUserId} from '../../../utils/authorization' -import OpenAIServerManager from '../../../utils/OpenAIServerManager' -import standardError from '../../../utils/standardError' -import isValid from '../../isValid' -import {MutationResolvers} from '../resolverTypes' - -type Prompt = { - question: string - description: string -} - -type PromptsByTemplate = { - [templateId: string]: Prompt[] -} - -const getTemplateSuggestion: MutationResolvers['getTemplateSuggestion'] = async ( - _source, - {prompt}, - {authToken, dataLoader} -) => { - const viewerId = getUserId(authToken) - const organizationUsers = await dataLoader.get('organizationUsersByUserId').load(viewerId) - const userOrgIds = organizationUsers.map(({orgId}) => orgId) - const availableOrgIds = ['aGhostOrg', ...userOrgIds] - const allTemplates = (await dataLoader.get('meetingTemplatesByOrgId').loadMany(availableOrgIds)) - .filter(isValid) - .flat() - - const templateIds = allTemplates.map((template) => template.id) - const prompts = (await dataLoader.get('reflectPromptsByTemplateId').loadMany(templateIds)) - .filter(isValid) - .flat() - - const promptsByTemplate: PromptsByTemplate = {} - prompts.forEach((prompt) => { - const {templateId} = prompt - if (!promptsByTemplate[templateId]) { - promptsByTemplate[templateId] = [] - } - promptsByTemplate[templateId]!.push({ - question: prompt.question, - description: prompt.description - }) - }) - - const templatesWithPrompts = allTemplates.map((template) => ({ - templateId: template.id, - templateName: template.name, - prompts: promptsByTemplate[template.id] || [] - })) - - const manager = new OpenAIServerManager() - const templateRes = await manager.getTemplateSuggestion(templatesWithPrompts, prompt) - if (!templateRes) { - return standardError(new Error('Unable to get AI suggested template'), {userId: viewerId}) - } - - const data = { - suggestedTemplateId: templateRes.templateId, - explanation: templateRes.explanation - } - return data -} - -export default getTemplateSuggestion diff --git a/packages/server/graphql/public/typeDefs/GetTemplateSuggestionPayload.graphql b/packages/server/graphql/public/typeDefs/GetTemplateSuggestionPayload.graphql deleted file mode 100644 index 14ea93c2e95..00000000000 --- a/packages/server/graphql/public/typeDefs/GetTemplateSuggestionPayload.graphql +++ /dev/null @@ -1,4 +0,0 @@ -""" -Return value for getTemplateSuggestion, which could be an error -""" -union GetTemplateSuggestionPayload = ErrorPayload | GetTemplateSuggestionSuccess diff --git a/packages/server/graphql/public/typeDefs/GetTemplateSuggestionSuccess.graphql b/packages/server/graphql/public/typeDefs/GetTemplateSuggestionSuccess.graphql deleted file mode 100644 index ecb9431570f..00000000000 --- a/packages/server/graphql/public/typeDefs/GetTemplateSuggestionSuccess.graphql +++ /dev/null @@ -1,11 +0,0 @@ -type GetTemplateSuggestionSuccess { - """ - The template the AI suggested - """ - suggestedTemplate: MeetingTemplate! - - """ - The explanation from the AI - """ - explanation: String! -} diff --git a/packages/server/graphql/public/typeDefs/Mutation.graphql b/packages/server/graphql/public/typeDefs/Mutation.graphql index a679e5303e9..984c417eddb 100644 --- a/packages/server/graphql/public/typeDefs/Mutation.graphql +++ b/packages/server/graphql/public/typeDefs/Mutation.graphql @@ -1445,16 +1445,6 @@ type Mutation { """ createStripeSubscription(orgId: ID!, paymentMethodId: ID!): CreateStripeSubscriptionPayload! - """ - Ask the AI for a template suggestion - """ - getTemplateSuggestion( - """ - The question the user has for the AI - """ - prompt: String! - ): GetTemplateSuggestionPayload! - """ Sign up or login using Google """ diff --git a/packages/server/graphql/public/types/GetTemplateSuggestionSuccess.ts b/packages/server/graphql/public/types/GetTemplateSuggestionSuccess.ts deleted file mode 100644 index 7ba81a50884..00000000000 --- a/packages/server/graphql/public/types/GetTemplateSuggestionSuccess.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {GetTemplateSuggestionSuccessResolvers} from '../resolverTypes' - -export type GetTemplateSuggestionSuccessSource = { - suggestedTemplateId: string - explanation: string -} - -const GetTemplateSuggestionSuccess: GetTemplateSuggestionSuccessResolvers = { - suggestedTemplate: async ({suggestedTemplateId}, _args, {dataLoader}) => { - const template = await dataLoader.get('meetingTemplates').loadNonNull(suggestedTemplateId) - return template - }, - explanation: ({explanation}) => explanation -} - -export default GetTemplateSuggestionSuccess diff --git a/packages/server/utils/OpenAIServerManager.ts b/packages/server/utils/OpenAIServerManager.ts index 32728edaaa0..28f56511baa 100644 --- a/packages/server/utils/OpenAIServerManager.ts +++ b/packages/server/utils/OpenAIServerManager.ts @@ -1,4 +1,3 @@ -import JSON5 from 'json5' import OpenAI from 'openai' import {ModifyType} from '../graphql/public/resolverTypes' import {RetroReflection} from '../postgres/types' @@ -21,11 +20,6 @@ type Template = { prompts: Prompt[] } -type AITemplateSuggestion = { - templateId: string - explanation: string -} - class OpenAIServerManager { private openAIApi constructor() { @@ -201,44 +195,6 @@ class OpenAIServerManager { } } - async getTemplateSuggestion(templates: Template[], userPrompt: string) { - if (!this.openAIApi) return null - const promptText = `Based on the user's input "${userPrompt}", identify the most suitable meeting template from the list below and provide a JSON response in the format: { templateId: "the chosen template ID", explanation: "reason for choosing this template" }. The explanation should be concise. Available templates are: ${templates - .map( - (template) => - `ID: ${template.templateId}, Name: ${template.templateName}, Prompts: ${template.prompts - .map((prompt) => `${prompt.question} - ${prompt.description}`) - .join('; ')}` - ) - .join('. ')}.` - - try { - const response = await this.openAIApi.chat.completions.create({ - model: 'gpt-4o-mini', - messages: [ - { - role: 'user', - content: promptText - } - ], - temperature: 0.7, - top_p: 1, - frequency_penalty: 0, - presence_penalty: 0 - }) - - const templateResponse = (response.choices[0]?.message?.content?.trim() as string) ?? null - const parsedResponse = JSON5.parse(templateResponse) - return parsedResponse as AITemplateSuggestion - } catch (e) { - const error = - e instanceof Error ? e : new Error('OpenAI failed to generate the suggested template') - Logger.error(error.message) - sendToSentry(error) - return null - } - } - async groupReflections(reflectionsText: string[], themes: string[]) { if (!this.openAIApi) return null From 71147b1ac40433a6c70dddc9fb05afbaa4a34a38 Mon Sep 17 00:00:00 2001 From: Nick O'Ferrall Date: Thu, 21 Nov 2024 15:20:34 +0100 Subject: [PATCH 2/3] remove template and prompt types --- packages/server/utils/OpenAIServerManager.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/server/utils/OpenAIServerManager.ts b/packages/server/utils/OpenAIServerManager.ts index 28f56511baa..d86205a69f7 100644 --- a/packages/server/utils/OpenAIServerManager.ts +++ b/packages/server/utils/OpenAIServerManager.ts @@ -4,22 +4,11 @@ import {RetroReflection} from '../postgres/types' import {Logger} from './Logger' import sendToSentry from './sendToSentry' -type Prompt = { - question: string - description: string -} - type InsightResponse = { wins: string[] challenges: string[] } -type Template = { - templateId: string - templateName: string - prompts: Prompt[] -} - class OpenAIServerManager { private openAIApi constructor() { From f955f2730bf11000017d9e2423506188b572f52f Mon Sep 17 00:00:00 2001 From: Nick O'Ferrall Date: Tue, 26 Nov 2024 17:59:23 +0000 Subject: [PATCH 3/3] re-add searchBar --- package.json | 3 +-- .../components/ActivityLibrary/ActivityLibrary.tsx | 9 +++++++++ yarn.lock | 9 ++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 15570f8ab71..4f08d579d55 100644 --- a/package.json +++ b/package.json @@ -69,8 +69,7 @@ "git-url-parse": "12.0.0", "fbjs": "^3.0.0", "parse-url": "^8.1.0", - "recursive-readdir": "^2.2.3", - "json5": "^2.2.3" + "recursive-readdir": "^2.2.3" }, "devDependencies": { "@babel/core": "^7.20.12", diff --git a/packages/client/components/ActivityLibrary/ActivityLibrary.tsx b/packages/client/components/ActivityLibrary/ActivityLibrary.tsx index fe283c85aae..da2547456e0 100644 --- a/packages/client/components/ActivityLibrary/ActivityLibrary.tsx +++ b/packages/client/components/ActivityLibrary/ActivityLibrary.tsx @@ -356,6 +356,15 @@ export const ActivityLibrary = (props: Props) => { Start Activity +
+ { + onQueryChange(e) + setSearch(e.target.value) + }} + /> +