aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/apis/gpt/GPT.ts50
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.tsx24
2 files changed, 43 insertions, 31 deletions
diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts
index 7878e9bfe..af9cdd2d1 100644
--- a/src/client/apis/gpt/GPT.ts
+++ b/src/client/apis/gpt/GPT.ts
@@ -11,10 +11,12 @@ export enum GPTDocCommand {
export const DescriptionSeperator = '======';
export const DocSeperator = '------';
+export const DataSeperator = '>>>>>>';
export enum TextClassifications {
- Title = 'word', //a few words
+ Title = 'word', //a few words
Caption = 'sentence', //few sentences
- LengthyDescription = 'paragraphs' }
+ LengthyDescription = 'paragraphs',
+}
enum GPTCallType {
SUMMARY = 'summary',
@@ -38,11 +40,12 @@ enum GPTCallType {
MAKERUBRIC = 'make_rubric', // create a definition rubric for a document to be used when quizzing the user
COMMANDTYPE = 'command_type', // Determine the type of command being made (GPTQueryType - eg., AssignTags, Sort, Filter, DocInfo, GenInfo) and possibly some parameters (eg, Tag type for Tags)
SUBSETDOCS = 'subset_docs', // select a subset of documents based on their descriptions
+ TAGDOCS = 'tag_docs', // choose a tags for each Doc
DOCINFO = 'doc_info', // provide information about a document
SORTDOCS = 'sort_docs',
CLASSIFYTEXTMINIMAL = 'classify_text_minimal', // classify text into one of the three categories: title, caption, lengthy description
CLASSIFYTEXTFULL = 'classify_text_full', //tags pdf content
- GENERATESCRAPBOOK = 'generate_scrapbook'
+ GENERATESCRAPBOOK = 'generate_scrapbook',
}
type GPTCallOpts = {
@@ -55,14 +58,12 @@ type GPTCallOpts = {
const callTypeMap: { [type in GPTCallType]: GPTCallOpts } = {
// newest model: gpt-4
summary: { model: 'gpt-4-turbo', maxTokens: 256, temp: 0.5, prompt: 'Summarize the text given in simpler terms.' },
-
-
+
sort_docs: {
model: 'gpt-4o',
maxTokens: 2048,
temp: 0.25,
- prompt:
- `The user is going to give you a list of descriptions.
+ prompt: `The user is going to give you a list of descriptions.
Each one is separated by '${DescriptionSeperator}' on either side.
Descriptions will vary in length, so make sure to only separate when you see '${DescriptionSeperator}'.
Sort them by the user's specifications.
@@ -71,7 +72,6 @@ const callTypeMap: { [type in GPTCallType]: GPTCallOpts } = {
It is VERY important that you format it exactly as described, ensuring the proper number of '${DescriptionSeperator[0]}' and '${DocSeperator[0]}' (${DescriptionSeperator.length} of each) and NO commas`,
},
-
edit: { model: 'gpt-4-turbo', maxTokens: 256, temp: 0.5, prompt: 'Reword the text.' },
stack: {
model: 'gpt-4o',
@@ -100,7 +100,7 @@ const callTypeMap: { [type in GPTCallType]: GPTCallOpts } = {
temp: 0.25,
prompt: `Based on the content of the the text, classify it into the
most appropriate category: '${TextClassifications.Title}' if it is a few words, '${TextClassifications.Caption}' if it is a couple sentences or less, or '${TextClassifications.LengthyDescription}' if it is a lengthy description. Output exclusively the classification in your response.
- `
+ `,
},
classify_text_full: {
model: 'gpt-4o',
@@ -109,7 +109,7 @@ const callTypeMap: { [type in GPTCallType]: GPTCallOpts } = {
prompt: `Based on the content of the the text, classify it into the
most appropriate category: '${TextClassifications.Title}', '${TextClassifications.Caption}', or '${TextClassifications.LengthyDescription}'.
Then provide five more descriptive tags (single words) separated by spaces.
- Finally, include a more detailed summary phrase tag using underscores, for a total of seven tags.`
+ Finally, include a more detailed summary phrase tag using underscores, for a total of seven tags.`,
},
describe: { model: 'gpt-4-vision-preview', maxTokens: 2048, temp: 0, prompt: 'Describe these images in 3-5 words' },
flashcard: {
@@ -174,7 +174,7 @@ const callTypeMap: { [type in GPTCallType]: GPTCallOpts } = {
model: 'gpt-4o',
maxTokens: 2048,
temp: 0.5,
- prompt: `Generate an aesthetically pleasing scrapbook layout preset based on these items.
+ prompt: `Generate an aesthetically pleasing scrapbook layout preset based on these items.
Return your response as JSON in the format:
[{
"type": rich text or image or pdf or video or collection
@@ -191,22 +191,32 @@ const callTypeMap: { [type in GPTCallType]: GPTCallOpts } = {
tag:
x: , y: , width: , height:
}
- ] `
-
- },
+ ] `,
+ },
command_type: {
model: 'gpt-4-turbo',
maxTokens: 1024,
temp: 0,
- prompt: `I'm going to provide you with a question.
- Based on the question, is the user asking you to
- ${GPTDocCommand.AssignTags}. Assigns docs with tags(like star / heart etc)/labels.
+ prompt: `Is the provided command/question asking you to:
+ ${GPTDocCommand.AssignTags}. Choose a descriptive tag/label.
${GPTDocCommand.GetInfo}. Provide information about a specific doc.
${GPTDocCommand.Filter}. Filter docs based on a question/information.
${GPTDocCommand.Sort}. Put docs in a specific order.
- Answer with only the number for ${GPTDocCommand.GetInfo}-${GPTDocCommand.Sort}.
- For number one, provide the number (${GPTDocCommand.AssignTags}) and the appropriate tag`,
+ Answer with only the number, do not add any other punctuation or formatting of any kind`,
+ },
+ tag_docs: {
+ model: 'gpt-4-turbo',
+ maxTokens: 1024,
+ temp: 0,
+ prompt: `I'm going to give you a list of descriptions.
+ Each one is separated by '${DescriptionSeperator}' on either side.
+ Descriptions will vary in length, so make sure to only separate when you see '${DescriptionSeperator}'.
+ Based on the question/command the user asks, provide a tag label of the given descriptions that best matches the user's specifications.
+ Format your response precisely as a single string that prints each description followed by '${DataSeperator}' followed by the label followed by '${DescriptionSeperator}'.
+ Do not use any additional formatting marks or punctuation'.
+ Immediately afterward, surrounded by '${DocSeperator}' on BOTH SIDES, provide some insight into your reasoning for the way you sorted (and mention nothing about the formatting details given in this description).
+ `,
},
subset_docs: {
model: 'gpt-4-turbo',
@@ -284,7 +294,7 @@ const gptImageCall = async (prompt: string, n?: number) => {
n: n ?? 1,
size: '1024x1024',
});
- return response.data.map((data: Image) => data.url);
+ return (response.data ?? []).map((data: Image) => data.url);
// return response.data.data[0].url;
} catch (err) {
console.error(err);
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index 660284397..ec269cc6c 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -11,7 +11,7 @@ import { ClientUtils } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
import { NumCast, StrCast } from '../../../../fields/Types';
import { Networking } from '../../../Network';
-import { DescriptionSeperator, DocSeperator, GPTCallType, GPTDocCommand, gptAPICall, gptImageCall } from '../../../apis/gpt/GPT';
+import { DataSeperator, DescriptionSeperator, DocSeperator, GPTCallType, GPTDocCommand, gptAPICall, gptImageCall } from '../../../apis/gpt/GPT';
import { DocUtils } from '../../../documents/DocUtils';
import { Docs } from '../../../documents/Documents';
import { SettingsManager } from '../../../util/SettingsManager';
@@ -145,20 +145,22 @@ export class GPTPopup extends ObservableReactComponent<object> {
break;
} // prettier-ignore
- gptOutput.split('======').filter(item => item.trim() !== '') // Split output into individual document contents
- .map(docContentRaw => textToDocMap.get(docContentRaw.replace(/\n/g, ' ').trim())) // the find the corresponding Doc using textToDoc map
- .filter(doc => doc).map(doc => doc!) // filter out undefined values
- .forEach((doc, index) => {
+ gptOutput.split(DescriptionSeperator).filter(item => item.trim() !== '') // Split output into individual document contents
+ .map(docContentRaw => docContentRaw.replace(/\n/g, ' ').trim())
+ .map(docContentRaw => ({doc: textToDocMap.get(docContentRaw.split(DataSeperator)[0]), data: docContentRaw.split(DataSeperator)[1] })) // the find the corresponding Doc using textToDoc map
+ .filter(({doc}) => doc).map(({doc, data}) => ({doc:doc!, data})) // filter out undefined values
+ .forEach(({doc, data}, index) => {
switch (questionType) {
case GPTDocCommand.Sort:
doc[ChatSortField] = index;
break;
case GPTDocCommand.AssignTags:
- if (args) {
- const hashTag = args.startsWith('#') ? args : '#' + args[0].toLowerCase() + args.slice(1);
- const filterTag = Doc.MyFilterHotKeys.map(key => StrCast(key.toolType)).find(key => key.includes(args)) ?? hashTag;
- TagItem.addTagToDoc(doc, filterTag);
- }
+ TagItem.addTagToDoc(doc, data.startsWith('#') ? data : '#'+data);
+ // if (args) {
+ // const hashTag = args.startsWith('#') ? args : '#' + args[0].toLowerCase() + args.slice(1);
+ // const filterTag = Doc.MyFilterHotKeys.map(key => StrCast(key.toolType)).find(key => key.includes(args)) ?? hashTag;
+ // TagItem.addTagToDoc(doc, filterTag);
+ // }
break;
case GPTDocCommand.Filter:
TagItem.addTagToDoc(doc, GPTPopup.ChatTag);
@@ -241,7 +243,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
gptAPICall(userPrompt, GPTCallType.COMMANDTYPE, undefined, true).then((commandType, args = commandType.split(' ').slice(1).join(' ')) =>
(async () => {
switch (this.NumberToCommandType(commandType)) {
- case GPTDocCommand.AssignTags:
+ case GPTDocCommand.AssignTags:return this._documentDescriptions?.then(descs => gptAPICall(userPrompt, GPTCallType.TAGDOCS, descs)) ?? "";
case GPTDocCommand.Filter: return this._documentDescriptions?.then(descs => gptAPICall(userPrompt, GPTCallType.SUBSETDOCS, descs)) ?? "";
case GPTDocCommand.Sort: return this._documentDescriptions?.then(descs => gptAPICall(userPrompt, GPTCallType.SORTDOCS, descs)) ?? "";
default: return Doc.getDescription(DocumentView.SelectedDocs().lastElement()).then(desc => gptAPICall(userPrompt, GPTCallType.DOCINFO, desc));