0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-11-23 16:37:52 +01:00

feat(max): OpenAI data processing opt-in (#26248)

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Michael Matloka 2024-11-19 14:27:35 +01:00 committed by GitHub
parent 7b36e5f3d9
commit 5d49d239f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 106 additions and 22 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -959,7 +959,7 @@ export const HedgehogBuddy = React.forwardRef<HTMLDivElement, HedgehogBuddyProps
useEffect(() => {
onPositionChange?.(actor)
}, [actor.x, actor.y])
}, [actor.x, actor.y, actor.direction])
const onClick = (): void => {
!actor.isDragging && _onClick?.(actor)

View File

@ -199,7 +199,7 @@ export const Popover = React.forwardRef<HTMLDivElement, PopoverProps>(function P
if (visible && referenceRef?.current && floatingElement) {
return autoUpdate(referenceRef.current, floatingElement, update)
}
}, [visible, referenceRef?.current, floatingElement, ...additionalRefs])
}, [visible, placement, referenceRef?.current, floatingElement, ...additionalRefs])
const floatingContainer = useFloatingContainer()

View File

@ -1,8 +1,11 @@
import { useValues } from 'kea'
import { offset } from '@floating-ui/react'
import { LemonButton, Popover } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { HedgehogBuddy } from 'lib/components/HedgehogBuddy/HedgehogBuddy'
import { hedgehogBuddyLogic } from 'lib/components/HedgehogBuddy/hedgehogBuddyLogic'
import { useMemo } from 'react'
import { useMemo, useState } from 'react'
import { maxGlobalLogic } from './maxGlobalLogic'
import { maxLogic } from './maxLogic'
const HEADLINES = [
@ -14,8 +17,12 @@ const HEADLINES = [
export function Intro(): JSX.Element {
const { hedgehogConfig } = useValues(hedgehogBuddyLogic)
const { acceptDataProcessing } = useActions(maxGlobalLogic)
const { dataProcessingAccepted } = useValues(maxGlobalLogic)
const { sessionId } = useValues(maxLogic)
const [hedgehogDirection, setHedgehogDirection] = useState<'left' | 'right'>('right')
const headline = useMemo(() => {
return HEADLINES[parseInt(sessionId.split('-').at(-1) as string, 16) % HEADLINES.length]
}, [])
@ -23,22 +30,52 @@ export function Intro(): JSX.Element {
return (
<>
<div className="flex">
<HedgehogBuddy
static
hedgehogConfig={{
...hedgehogConfig,
walking_enabled: false,
controls_enabled: false,
}}
onClick={(actor) => {
if (Math.random() < 0.01) {
actor.setOnFire()
} else {
actor.setRandomAnimation()
<Popover
overlay={
<div className="m-1.5">
<p className="font-medium text-pretty mb-1.5">
Hi! I use OpenAI services to analyze your data,
<br />
so that you can focus on building. This <em>can</em> include
<br />
personal data of your users, if you're capturing it.
<br />
<em>Your data won't be used for training models.</em>
</p>
<LemonButton type="secondary" size="small" onClick={() => acceptDataProcessing()}>
Got it, I accept OpenAI processing data
</LemonButton>
</div>
}
placement={`${hedgehogDirection}-end`}
middleware={[offset(-12)]}
showArrow
visible={!dataProcessingAccepted}
>
<HedgehogBuddy
static
hedgehogConfig={{
...hedgehogConfig,
walking_enabled: false,
controls_enabled: false,
}}
onClick={(actor) => {
if (Math.random() < 0.01) {
actor.setOnFire()
} else {
actor.setRandomAnimation()
}
}}
onActorLoaded={(actor) =>
setTimeout(() => {
actor.setAnimation('wave')
// Always start out facing right so that the data processing popover is more readable
actor.direction = 'right'
}, 100)
}
}}
onActorLoaded={(actor) => setTimeout(() => actor.setAnimation('wave'), 100)}
/>
onPositionChange={(actor) => setHedgehogDirection(actor.direction)}
/>
</Popover>
</div>
<div className="text-center mb-3">
<h2 className="text-2xl font-bold mb-2 text-balance">{headline}</h2>

View File

@ -8,6 +8,7 @@ import { mswDecorator, useStorybookMocks } from '~/mocks/browser'
import { chatResponseChunk, failureChunk, generationFailureChunk } from './__mocks__/chatResponse.mocks'
import { MaxInstance } from './Max'
import { maxGlobalLogic } from './maxGlobalLogic'
import { maxLogic } from './maxLogic'
const meta: Meta = {
@ -31,6 +32,12 @@ export default meta
const SESSION_ID = 'b1b4b3b4-1b3b-4b3b-1b3b4b3b4b3b'
const Template = ({ sessionId: SESSION_ID }: { sessionId: string }): JSX.Element => {
const { acceptDataProcessing } = useActions(maxGlobalLogic)
useEffect(() => {
acceptDataProcessing()
}, [])
return (
<div className="relative flex flex-col h-fit">
<BindLogic logic={maxLogic} props={{ sessionId: SESSION_ID }}>
@ -56,6 +63,11 @@ export const Welcome: StoryFn = () => {
],
},
})
const { acceptDataProcessing } = useActions(maxGlobalLogic)
useEffect(() => {
// We override data processing opt-in to false, so that wee see the welcome screen as a first-time user would
acceptDataProcessing(false)
}, [])
return <Template sessionId={SESSION_ID} />
}
@ -65,7 +77,7 @@ export const WelcomeSuggestionsAvailable: StoryFn = () => {
useEffect(() => {
loadCurrentProjectSuccess({ ...MOCK_DEFAULT_PROJECT, product_description: 'A Storybook test.' })
})
}, [])
return <Welcome />
}
@ -81,7 +93,7 @@ export const WelcomeLoadingSuggestions: StoryFn = () => {
useEffect(() => {
loadCurrentProjectSuccess({ ...MOCK_DEFAULT_PROJECT, product_description: 'A Storybook test.' })
})
}, [])
return <Template sessionId={SESSION_ID} />
}

View File

@ -4,9 +4,11 @@ import clsx from 'clsx'
import { useActions, useValues } from 'kea'
import { useEffect, useRef } from 'react'
import { maxGlobalLogic } from './maxGlobalLogic'
import { maxLogic } from './maxLogic'
export function QuestionInput(): JSX.Element {
const { dataProcessingAccepted } = useValues(maxGlobalLogic)
const { question, thread, threadLoading } = useValues(maxLogic)
const { askMax, setQuestion } = useActions(maxLogic)
@ -48,7 +50,15 @@ export function QuestionInput(): JSX.Element {
type={isFloating && !question ? 'secondary' : 'primary'}
onClick={() => askMax(question)}
tooltip="Let's go!"
disabledReason={!question ? 'I need some input first' : threadLoading ? 'Thinking…' : undefined}
disabledReason={
!dataProcessingAccepted
? 'Please accept OpenAI processing data'
: !question
? 'I need some input first'
: threadLoading
? 'Thinking…'
: undefined
}
size="small"
icon={<IconArrowRight />}
/>

View File

@ -4,9 +4,11 @@ import { useActions, useValues } from 'kea'
import { sidePanelSettingsLogic } from '~/layout/navigation-3000/sidepanel/panels/sidePanelSettingsLogic'
import { maxGlobalLogic } from './maxGlobalLogic'
import { maxLogic } from './maxLogic'
export function QuestionSuggestions(): JSX.Element {
const { dataProcessingAccepted } = useValues(maxGlobalLogic)
const { visibleSuggestions, allSuggestionsLoading, currentProject } = useValues(maxLogic)
const { askMax, shuffleVisibleSuggestions } = useActions(maxLogic)
const { openSettingsPanel } = useActions(sidePanelSettingsLogic)
@ -56,6 +58,9 @@ export function QuestionSuggestions(): JSX.Element {
sideIcon={<IconArrowUpRight />}
center
className="shrink"
disabledReason={
!dataProcessingAccepted ? 'Please accept OpenAI processing data' : undefined
}
>
{suggestion}
</LemonButton>

View File

@ -0,0 +1,19 @@
import { actions, kea, path, reducers } from 'kea'
import type { maxGlobalLogicType } from './maxGlobalLogicType'
export const maxGlobalLogic = kea<maxGlobalLogicType>([
path(['scenes', 'max', 'maxGlobalLogic']),
actions({
acceptDataProcessing: (testOnlyOverride?: boolean) => ({ testOnlyOverride }),
}),
reducers({
dataProcessingAccepted: [
false,
{ persist: true },
{
acceptDataProcessing: (_, { testOnlyOverride }) => testOnlyOverride ?? true,
},
],
}),
])

View File

@ -99,6 +99,7 @@ export const maxLogic = kea<maxLogicType>([
],
}),
loaders({
// TODO: Move question suggestions to `maxGlobalLogic`, which will make this logic `maxThreadLogic`
allSuggestions: [
null as string[] | null,
{