From c76505f56a83625e3993427838aaee0c54c5fb81 Mon Sep 17 00:00:00 2001 From: alyssaf16 Date: Thu, 6 Jun 2024 09:53:12 -0400 Subject: Fixes to chatcard and quizcard --- src/client/apis/gpt/GPT.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/apis') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 05007960d..b036349dc 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -51,7 +51,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { model: 'gpt-4-turbo', maxTokens: 1024, temp: 0, - prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', + prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If the Rubric is incorrect, explain why. If there are no differences, say correct. If it is empty, say there is nothing for me to evaluate.', }, }; -- cgit v1.2.3-70-g09d2 From ad32c1606395cdc71ba50eb9b51d3a9d3b707ca0 Mon Sep 17 00:00:00 2001 From: alyssaf16 Date: Tue, 18 Jun 2024 15:23:12 -0400 Subject: working on various image flashcard ideas --- src/client/apis/gpt/GPT.ts | 7 +- src/client/views/MarqueeAnnotator.tsx | 1 + .../views/collections/CollectionCardDeckView.tsx | 2 +- .../views/collections/CollectionCarouselView.tsx | 4 +- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/ComparisonBox.tsx | 18 +- src/client/views/nodes/ImageBox.scss | 21 ++ src/client/views/nodes/ImageBox.tsx | 232 +++++++++++++++++++++ src/client/views/pdf/AnchorMenu.tsx | 47 ++--- src/client/views/pdf/Annotation.scss | 32 +-- src/client/views/pdf/PDFViewer.scss | 21 ++ src/client/views/pdf/PDFViewer.tsx | 52 +++++ 12 files changed, 383 insertions(+), 56 deletions(-) (limited to 'src/client/apis') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index b036349dc..7bcd541c7 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -25,7 +25,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { // newest model: gpt-4 summary: { model: 'gpt-4-turbo', maxTokens: 256, temp: 0.5, prompt: 'Summarize the text given in simpler terms.' }, edit: { model: 'gpt-4-turbo', maxTokens: 256, temp: 0.5, prompt: 'Reword the text.' }, - flashcard: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'Make flashcards out of this text with each question and answer labeled. Do not label each flashcard and do not include asterisks: ' }, + flashcard: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'Make flashcards out of this text with each question and answer labeled as question and answer. Do not label each flashcard and do not include asterisks: ' }, completion: { model: 'gpt-4-turbo', maxTokens: 256, temp: 0.5, prompt: "You are a helpful assistant. Answer the user's prompt." }, mermaid: { model: 'gpt-4-turbo', @@ -120,7 +120,7 @@ const gptGetEmbedding = async (src: string): Promise => { return []; } }; -const gptImageLabel = async (src: string): Promise => { +const gptImageLabel = async (src: string, prompt: string): Promise => { try { const response = await openai.chat.completions.create({ model: 'gpt-4o', @@ -128,7 +128,7 @@ const gptImageLabel = async (src: string): Promise => { { role: 'user', content: [ - { type: 'text', text: 'Give three to five labels to describe this image.' }, + { type: 'text', text: prompt }, { type: 'image_url', image_url: { @@ -141,6 +141,7 @@ const gptImageLabel = async (src: string): Promise => { ], }); if (response.choices[0].message.content) { + console.log(response.choices[0].message.content); return response.choices[0].message.content; } return 'Missing labels'; diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index c18ac6738..c7ffce2b4 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -34,6 +34,7 @@ export interface MarqueeAnnotatorProps { getPageFromScroll?: (top: number) => number; finishMarquee: (x?: number, y?: number) => void; anchorMenuClick?: () => undefined | ((anchor: Doc) => void); + anchorMenuFlashcard?: () => Promise; anchorMenuCrop?: (anchor: Doc | undefined, addCrop: boolean) => Doc | undefined; highlightDragSrcColor?: string; } diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index de46180e6..50af9df9e 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -373,7 +373,7 @@ export class CollectionCardView extends CollectionSubView() { const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`; try { const hrefBase64 = await CollectionCardView.imageUrlToBase64(hrefComplete); - const response = await gptImageLabel(hrefBase64); + const response = await gptImageLabel(hrefBase64, 'Give three to five labels to describe this image.'); image[DocData].description = response.trim(); return response; // Return the response from gptImageLabel } catch (error) { diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index f2d634eaa..6976deea5 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -46,14 +46,14 @@ export class CollectionCarouselView extends CollectionSubView() { @observable private _filterMessage: string | undefined; get practiceField() { return this.fieldKey + "_practice"; } // prettier-ignore get sideField() { return "_" + this.fieldKey + "_usePath"; } // prettier-ignore - get starField() { return this.fieldKey + "_star"; } // prettier-ignore + get starField() { return "star"; } // prettier-ignore constructor(props: any) { super(props); makeObservable(this); // this.setModes(); this.layoutDoc.filterOp = cardMode.ALL; - Doc.setDocFilter(this.Document, 'data_star', undefined, 'match'); + Doc.setDocFilter(this.Document, 'star', undefined, 'match'); this.layoutDoc.practiceMode = practiceMode.NORMAL; this.layoutDoc._carousel_index = 0; } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index dc15c83c5..0afda3e64 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -440,7 +440,7 @@ export class MarqueeView extends ObservableReactComponent !hrefBase64 ? undefined : - gptImageLabel(hrefBase64).then(labels => + gptImageLabel(hrefBase64, 'Give three to five labels to describe this image.').then(labels => Promise.all(labels.split('\n').map(label => gptGetEmbedding(label))).then(embeddings => ({ doc, embeddings, labels }))) ); // prettier-ignore }); diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 2fc297bec..3d33ff862 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -92,6 +92,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() Doc.SetContainer(droppedDocuments.lastElement(), this.dataDoc); !added && e.preventDefault(); e.stopPropagation(); // prevent parent Doc from registering new position so that it snaps back into place + // this.childActive = false; return added; } return undefined; @@ -257,7 +258,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() newCol['x'] = this.layoutDoc['x']; newCol['y'] = NumCast(this.layoutDoc['y']) + 50; newCol.type_collection = 'carousel'; - console.log(newCol.data); + // console.log(newCol.data); if (gpt) { this._props.DocumentView?.()._props.addDocument?.(newCol); @@ -270,13 +271,13 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() } gptFlashcardPile = async () => { - var text = (await this.askGPT(GPTCallType.FLASHCARD)) || ''; + var text = await this.askGPT(GPTCallType.FLASHCARD); - var senArr = text.trim().split('Question: '); + var senArr = text?.split('Question: '); var collectionArr: Doc[] = []; - for (let i = 1; i < senArr.length; i++) { - const newDoc = Docs.Create.ComparisonDocument(senArr[i].trim(), { _layout_isFlashcard: true, _width: 300, _height: 300 }); - newDoc.text = senArr[i].trim(); + for (let i = 1; i < senArr?.length!; i++) { + const newDoc = Docs.Create.ComparisonDocument(senArr![i], { _layout_isFlashcard: true, _width: 300, _height: 300 }); + newDoc.text = senArr![i]; collectionArr.push(newDoc); } this.createFlashcardPile(collectionArr, true); @@ -451,13 +452,12 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() if (callType == GPTCallType.QUIZ) this._outputValue = res; // DocCast(this.dataDoc[this.props.fieldKey + '_0'])[DocData].text = res; // this._outputValue = res; - - if (callType === GPTCallType.FLASHCARD) { + else if (callType === GPTCallType.FLASHCARD) { // console.log(res); this._loading = false; return res; } - console.log(res); + // console.log(res); } catch (err) { console.error('GPT call failed'); } diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss index 3ffda5a35..be68ac8cd 100644 --- a/src/client/views/nodes/ImageBox.scss +++ b/src/client/views/nodes/ImageBox.scss @@ -139,3 +139,24 @@ .imageBox-fadeBlocker-hover { opacity: 0; } + +.loading-spinner { + position: absolute; + display: flex; + justify-content: center; + align-items: center; + height: 100%; + width: 100%; + // left: 50%; + // top: 50%; + z-index: 200; + font-size: 20px; + font-weight: bold; + color: #17175e; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index e4b3a1b9b..ff938df78 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -35,6 +35,15 @@ import { FieldView, FieldViewProps } from './FieldView'; import { FocusViewOptions } from './FocusViewOptions'; import './ImageBox.scss'; import { OpenWhere } from './OpenWhere'; +import { URLField } from '../../../fields/URLField'; +import { gptImageLabel } from '../../apis/gpt/GPT'; +import ReactLoading from 'react-loading'; +import { FollowLinkScript } from '../../documents/DocUtils'; +import { basename } from 'path'; +import { ImageUtility } from './generativeFill/generativeFillUtils/ImageHandler'; +import { dropActionType } from '../../util/DropActionTypes'; +import { canvasSize } from './generativeFill/generativeFillUtils/generativeFillConstants'; +import axios from 'axios'; export class ImageEditorData { // eslint-disable-next-line no-use-before-define @@ -59,6 +68,8 @@ export class ImageEditorData { public static get AddDoc() { return ImageEditorData.imageData.addDoc; } // prettier-ignore public static set AddDoc(addDoc: Opt<(doc: Doc | Doc[], annotationKey?: string) => boolean>) { ImageEditorData.set(this.imageData.open, this.imageData.rootDoc, this.imageData.source, addDoc); } // prettier-ignore } + +const API_URL = 'https://api.unsplash.com/search/photos'; @observer export class ImageBox extends ViewBoxAnnotatableComponent() { public static LayoutString(fieldKey: string) { @@ -73,9 +84,14 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { private _marqueeref = React.createRef(); private _mainCont: React.RefObject = React.createRef(); private _annotationLayer: React.RefObject = React.createRef(); + private _imageRef: HTMLImageElement | null = null; //