diff options
author | Sophie Zhang <sophie_zhang@brown.edu> | 2023-11-02 13:10:48 -0400 |
---|---|---|
committer | Sophie Zhang <sophie_zhang@brown.edu> | 2023-11-02 13:10:48 -0400 |
commit | 8fccdb8c21015eb9204de7c24a80ece82f338d8e (patch) | |
tree | 4b54625dc50c1ecba466c8e02f1fe2acc0cce165 | |
parent | a1d00a36ef1afa97198a825bd25ebb4c5e598848 (diff) |
gpt stylization
-rw-r--r-- | src/client/apis/gpt/customization.ts | 51 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 51 | ||||
-rw-r--r-- | src/client/views/nodes/trails/PresBox.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/trails/PresElementBox.tsx | 24 |
4 files changed, 99 insertions, 29 deletions
diff --git a/src/client/apis/gpt/customization.ts b/src/client/apis/gpt/customization.ts index 3d9a0ead3..20dac0a4e 100644 --- a/src/client/apis/gpt/customization.ts +++ b/src/client/apis/gpt/customization.ts @@ -16,6 +16,10 @@ const prompts: { [key: string]: PromptInfo } = { }, }; +export const addCustomizationProperty = (type: CustomizationType, name: string, description: string, values?: string[]) => { + values ? prompts[type].features.push({ name, description, values }) : prompts[type].features.push({ name, description }); +}; + const setupPresSlideCustomization = () => { addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'title', 'is the title/name of the slide.'); addCustomizationProperty(CustomizationType.PRES_TRAIL_SLIDE, 'presentation_transition', 'is a number in milliseconds for how long it should take to transition/move to a slide.'); @@ -24,10 +28,6 @@ const setupPresSlideCustomization = () => { setupPresSlideCustomization(); -export const addCustomizationProperty = (type: CustomizationType, name: string, description: string, values?: string[]) => { - values ? prompts[type].features.push({ name, description, values }) : prompts[type].features.push({ name, description }); -}; - export const gptTrailSlideCustomization = async (inputText: string) => { let prompt = prompts.trails.description; @@ -59,3 +59,46 @@ export const gptTrailSlideCustomization = async (inputText: string) => { return 'Error connecting with API.'; } }; + +// palette / styling +export const generatePalette = async (inputData: any) => { + let prompt = 'Dash is a hypermedia web application that allows users to organize documents of different media types into collections. I want you to come up with a cohesive color palette for a collection.'; + prompt += + 'I am going to give you a json object of this format:' + + JSON.stringify({ collectionDescription: 'string', documents: 'Document[]' }) + + '. collectionDescription is the title of the collection, which you should create a color palette based on. This is the document format:' + + JSON.stringify({ + id: 'number', + textSize: 'number', + textContent: 'string', + }) + + '. You are going to create a color palette based mostly on collectionDescription, and loosely on the text content and text size of the documents. Return a json object in this format:' + + JSON.stringify({ + collectionBackgroundColor: 'string', + documentsWithColors: 'DocumentWithColor[]', + }) + + '. collectionBackgroundColor, should be a string hex value for the background color of the collection. documentsWithColors has the same length and order of the input documents. DocumentWithColor has this format:' + + JSON.stringify({ + id: 'number', + color: 'string', + }) + + ", and each element’s color is based on the theme of the overall color palette and also by its document’s textContent. Please pay attention to aesthetics of how each document's color complement the background and each other and choose a variety of colors when appropriate. Respond with only the JSON object."; + + // console.log('Prompt', prompt); + try { + const response = await openai.createChatCompletion({ + model: 'gpt-4', + messages: [ + { role: 'system', content: prompt }, + { role: 'user', content: JSON.stringify(inputData) }, + ], + temperature: 0.1, + max_tokens: 2000, + }); + console.log(response.data.choices[0].message?.content); + return response.data.choices[0].message?.content; + } catch (err) { + console.log(err); + return 'Error connecting with API.'; + } +}; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 0c3033579..002ebf1ae 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -52,6 +52,7 @@ import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCurso import './CollectionFreeFormView.scss'; import { MarqueeView } from './MarqueeView'; import React = require('react'); +import { generatePalette } from '../../../apis/gpt/customization'; export type collectionFreeformViewProps = { NativeWidth?: () => number; @@ -1573,6 +1574,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection @action componentDidMount() { + this.printDoc(this.rootDoc); this.props.setContentView?.(this); super.componentDidMount?.(); this.props.setBrushViewer?.(this.brushView); @@ -1787,6 +1789,53 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection } }; + printDoc = (doc: Doc) => { + console.log('Printing keys'); + Object.keys(doc).forEach(key => { + console.log(key, ':', doc[key]); + }); + }; + + // gpt styling + @action + gptStyling = async () => { + console.log('Title', this.rootDoc.title); + console.log('bgcolor', this.layoutDoc._backgroundColor); + // doc.backgroundColor + console.log('styling'); + const inputDocs = this.childDocs.filter(doc => doc.type == 'rich text'); + const gptInput = inputDocs.map((doc, i) => ({ + id: i, + textContent: (doc.text as RichTextField)?.Text, + textSize: 16, + })); + + // inputDocs[0].backgroundColor = '#3392ff'; + + const collectionDescription = StrCast(this.rootDoc.title); + + console.log({ + collectionDescription, + documents: gptInput, + }); + + try { + const res = await generatePalette({ + collectionDescription, + documents: gptInput, + }); + console.log('done'); + if (typeof res === 'string') { + const resObj = JSON.parse(res); + console.log('Result ', resObj); + this.rootDoc.backgroundColor = resObj.collectionBackgroundColor; + (resObj.documentsWithColors as any[]).forEach((elem, i) => (inputDocs[i].backgroundColor = elem.color)); + } + } catch (err) { + console.error(err); + } + }; + onContextMenu = (e: React.MouseEvent) => { if (this.props.isAnnotationOverlay || !ContextMenu.Instance) return; @@ -1826,6 +1875,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection optionItems.push({ description: (this._showAnimTimeline ? 'Close' : 'Open') + ' Animation Timeline', event: action(() => (this._showAnimTimeline = !this._showAnimTimeline)), icon: 'eye' }); this.props.renderDepth && optionItems.push({ description: 'Use Background Color as Default', event: () => (Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor)), icon: 'palette' }); this.props.renderDepth && optionItems.push({ description: 'Fit Content Once', event: this.fitContentOnce, icon: 'object-group' }); + // gpt styling + this.props.renderDepth && optionItems.push({ description: 'Style with AI', event: this.gptStyling, icon: 'paint-brush' }); if (!Doc.noviceMode) { optionItems.push({ description: (!Doc.NativeWidth(this.layoutDoc) || !Doc.NativeHeight(this.layoutDoc) ? 'Freeze' : 'Unfreeze') + ' Aspect', event: this.toggleNativeDimensions, icon: 'snowflake' }); } diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 87ffb0112..19f271246 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -40,10 +40,10 @@ import ReactLoading from 'react-loading'; import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums'; import { IconButton, Type } from 'browndash-components'; import { AiOutlineSend } from 'react-icons/ai'; -import { gptTrailSlideCustomization } from '../../../apis/gpt/GPT'; import { DictationManager } from '../../../util/DictationManager'; import { BiMicrophone, BiX } from 'react-icons/bi'; import TextareaAutosize from 'react-textarea-autosize'; +import { gptTrailSlideCustomization } from '../../../apis/gpt/customization'; export interface pinDataTypes { scrollable?: boolean; diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 482d38f59..37f449001 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -26,10 +26,6 @@ import './PresElementBox.scss'; import { PresMovement } from './PresEnums'; import React = require('react'); import { TreeView } from '../../collections/TreeView'; -import { BranchingTrailManager } from '../../../util/BranchingTrailManager'; -import { MultiToggle, Type } from 'browndash-components'; -import { gptTrailSlideCustomization } from '../../../apis/gpt/GPT'; -import { DictationManager } from '../../../util/DictationManager'; /** * This class models the view a document added to presentation will have in the presentation. * It involves some functionality for its buttons and options. @@ -438,25 +434,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { // GPT - @action - customizeWithGPT = async (input: string) => { - const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect'; - - try { - const res = await gptTrailSlideCustomization(testInput); - if (typeof res === 'string') { - const resObj = JSON.parse(res); - console.log('Result ', resObj); - - for (let key in resObj) { - this.rootDoc[key] = resObj[key]; - } - } - } catch (err) { - console.error(err); - } - }; - @computed get presButtons() { const presBox = this.presBox; const presBoxColor = StrCast(presBox?._backgroundColor); @@ -568,7 +545,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { PresBox.Instance.setChatActive(true); PresBox.Instance.slideToModify = this.rootDoc; PresBox.Instance.recordDictation(); - // this.customizeWithGPT(''); }}> <FontAwesomeIcon icon={'message'} onPointerDown={e => e.stopPropagation()} /> </div> |