only_ever_generator 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap/app.js +63 -13
- package/dist/card_gen/generate_cards.js +19 -16
- package/dist/constants/prompts/card_gen_prompt.js +38 -135
- package/dist/index.js +6 -3
- package/package.json +3 -2
- package/src/bootstrap/app.ts +138 -67
- package/src/card_gen/generate_cards.ts +18 -15
- package/src/constants/prompts/card_gen_prompt.ts +38 -135
- package/src/index.ts +2 -2
package/dist/bootstrap/app.js
CHANGED
|
@@ -18,51 +18,66 @@ const typology_prompt_1 = require("../constants/prompts/typology_prompt");
|
|
|
18
18
|
const generate_typology_1 = require("../typology_gen/generate_typology");
|
|
19
19
|
const generate_args_1 = require("../utils/generate_args");
|
|
20
20
|
const source_data_1 = require("../constants/source_data");
|
|
21
|
-
|
|
21
|
+
function isEmpty(obj) {
|
|
22
|
+
return Object.keys(obj).length === 0;
|
|
23
|
+
}
|
|
24
|
+
/// OnlyEverGenerator
|
|
22
25
|
class OnlyEverGenerator {
|
|
23
26
|
constructor(apiKey, model, content, expected_fields) {
|
|
24
|
-
this.api_key =
|
|
25
|
-
this.parsedContent =
|
|
27
|
+
this.api_key = "";
|
|
28
|
+
this.parsedContent = "";
|
|
26
29
|
this.typologyResponse = {};
|
|
27
30
|
this.cardgenResponse = {};
|
|
28
31
|
this.summarizeResponse = {};
|
|
32
|
+
this.gapFillResponse = {};
|
|
29
33
|
this.api_key = apiKey;
|
|
30
|
-
this.openAiService = new open_ai_service_1.OpenAiService(apiKey, model !== null && model !== void 0 ? model :
|
|
34
|
+
this.openAiService = new open_ai_service_1.OpenAiService(apiKey, model !== null && model !== void 0 ? model : "gpt-3.5-turbo-1106");
|
|
31
35
|
this.parsedContent = new parse_source_content_1.ParseSourceContent(content).parse();
|
|
32
36
|
this.expectedFields = (0, source_data_1.returnFields)();
|
|
33
37
|
}
|
|
34
|
-
;
|
|
35
38
|
generate() {
|
|
36
39
|
return __awaiter(this, arguments, void 0, function* (generate_typology = false, generate_card = false) {
|
|
37
|
-
var _a, _b;
|
|
40
|
+
var _a, _b, _c;
|
|
38
41
|
let typologyPrompt = (0, typology_prompt_1.returnTypologyPrompt)();
|
|
39
42
|
let cardPrompt = (0, card_gen_prompt_1.returnCardGenPrompt)();
|
|
40
43
|
let args = new generate_args_1.GenerateArgs(generate_card, generate_typology, false, {
|
|
41
44
|
typology_prompt: typologyPrompt,
|
|
42
45
|
card_gen_prompt: cardPrompt,
|
|
43
|
-
summary_prompt:
|
|
46
|
+
summary_prompt: "",
|
|
44
47
|
});
|
|
45
48
|
const responseToReturn = [];
|
|
46
49
|
const whatNeedsToBeGenerated = args.getWhatNeedsToBeGenerated();
|
|
47
50
|
for (let elem of whatNeedsToBeGenerated)
|
|
48
|
-
if (elem ==
|
|
49
|
-
this.typologyResponse = yield this.generateTypology((_a = args.prompts.typology_prompt) !== null && _a !== void 0 ? _a :
|
|
51
|
+
if (elem == "generate_tyopology") {
|
|
52
|
+
this.typologyResponse = yield this.generateTypology((_a = args.prompts.typology_prompt) !== null && _a !== void 0 ? _a : "");
|
|
50
53
|
responseToReturn.push(this.typologyResponse);
|
|
51
54
|
}
|
|
52
|
-
else if (elem ==
|
|
53
|
-
this.cardgenResponse = yield this.generateCard((_b = args.prompts.card_gen_prompt) !== null && _b !== void 0 ? _b :
|
|
55
|
+
else if (elem == "generate_card") {
|
|
56
|
+
this.cardgenResponse = yield this.generateCard((_b = args.prompts.card_gen_prompt) !== null && _b !== void 0 ? _b : "", this.parsedContent + JSON.stringify(this.typologyResponse), false);
|
|
54
57
|
responseToReturn.push(this.cardgenResponse);
|
|
55
58
|
}
|
|
59
|
+
if (this.cardgenResponse.status_code == 200) {
|
|
60
|
+
let gapFill = this.gapFilling();
|
|
61
|
+
if (gapFill.remainingConcepts.length !== 0 ||
|
|
62
|
+
gapFill.remainingFacts.length !== 0) {
|
|
63
|
+
this.gapFillResponse = yield this.generateCard((_c = args.prompts.card_gen_prompt) !== null && _c !== void 0 ? _c : "", this.parsedContent +
|
|
64
|
+
"Generate cards only suitable for the given remaining concepts and facts" +
|
|
65
|
+
JSON.stringify(gapFill) +
|
|
66
|
+
"Exclude generating these cards" +
|
|
67
|
+
JSON.stringify(this.cardgenResponse.cards_data), true);
|
|
68
|
+
}
|
|
69
|
+
responseToReturn.push(this.gapFillResponse);
|
|
70
|
+
}
|
|
56
71
|
return responseToReturn;
|
|
57
72
|
});
|
|
58
73
|
}
|
|
59
74
|
_returnParsedContent() {
|
|
60
75
|
return this.parsedContent;
|
|
61
76
|
}
|
|
62
|
-
generateCard(prompt, content) {
|
|
77
|
+
generateCard(prompt, content, isGapFill) {
|
|
63
78
|
return __awaiter(this, void 0, void 0, function* () {
|
|
64
79
|
let generateCards = new generate_cards_1.GenerateCards(this.openAiService);
|
|
65
|
-
let cardgenResponse = yield generateCards.generateCards(prompt !== null && prompt !== void 0 ? prompt :
|
|
80
|
+
let cardgenResponse = yield generateCards.generateCards(prompt !== null && prompt !== void 0 ? prompt : "", content, isGapFill);
|
|
66
81
|
// let response = await this.openAiService?.sendRequest(prompt,this.parsedContent);
|
|
67
82
|
// response['type'] = 'card_gen';
|
|
68
83
|
return cardgenResponse;
|
|
@@ -74,5 +89,40 @@ class OnlyEverGenerator {
|
|
|
74
89
|
return response;
|
|
75
90
|
});
|
|
76
91
|
}
|
|
92
|
+
gapFilling() {
|
|
93
|
+
var _a, _b, _c, _d, _e;
|
|
94
|
+
let allConcepts = [];
|
|
95
|
+
let allFacts = [];
|
|
96
|
+
let generatedConceptsList = [];
|
|
97
|
+
let generatedFactsList = [];
|
|
98
|
+
if (!isEmpty(this.typologyResponse)) {
|
|
99
|
+
allConcepts.push(...((_a = this.typologyResponse.concepts) !== null && _a !== void 0 ? _a : []));
|
|
100
|
+
allFacts.push(...((_c = (_b = this.typologyResponse) === null || _b === void 0 ? void 0 : _b.facts) !== null && _c !== void 0 ? _c : []));
|
|
101
|
+
}
|
|
102
|
+
if (!isEmpty(this.cardgenResponse)) {
|
|
103
|
+
allConcepts.push(...((_d = this.cardgenResponse.missing_concepts) !== null && _d !== void 0 ? _d : []));
|
|
104
|
+
allFacts.push(...((_e = this.cardgenResponse.missing_facts) !== null && _e !== void 0 ? _e : []));
|
|
105
|
+
}
|
|
106
|
+
for (let card of this.cardgenResponse.cards_data) {
|
|
107
|
+
if (card.concepts.length != 0) {
|
|
108
|
+
generatedConceptsList.push(...card.concepts);
|
|
109
|
+
}
|
|
110
|
+
if (card.facts.length != 0) {
|
|
111
|
+
generatedFactsList.push(...card.facts);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
let generatedConceptsSet = Array.from(new Set(generatedConceptsList));
|
|
115
|
+
let generatedFactsSet = Array.from(new Set(generatedFactsList));
|
|
116
|
+
let remainingConcepts = allConcepts.filter((item) => !generatedConceptsSet.includes(item));
|
|
117
|
+
let remainingFacts = allFacts.filter((item) => !generatedFactsSet.includes(item));
|
|
118
|
+
return {
|
|
119
|
+
// allConcepts: allConcepts,
|
|
120
|
+
// allFacts: allFacts,
|
|
121
|
+
// generatedConcepts: generatedConceptsSet,
|
|
122
|
+
// generatedFacts: generatedFactsSet,
|
|
123
|
+
remainingConcepts: remainingConcepts,
|
|
124
|
+
remainingFacts: remainingFacts,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
77
127
|
}
|
|
78
128
|
exports.OnlyEverGenerator = OnlyEverGenerator;
|
|
@@ -14,12 +14,12 @@ class GenerateCards {
|
|
|
14
14
|
constructor(openAiService) {
|
|
15
15
|
this.openAiService = openAiService;
|
|
16
16
|
}
|
|
17
|
-
generateCards(prompt, parsedContent) {
|
|
17
|
+
generateCards(prompt, parsedContent, isGapFill) {
|
|
18
18
|
return __awaiter(this, void 0, void 0, function* () {
|
|
19
19
|
var _a, _b, _c;
|
|
20
20
|
let response = yield ((_a = this.openAiService) === null || _a === void 0 ? void 0 : _a.sendRequest(prompt, parsedContent));
|
|
21
|
-
console.log("response to card generation ", response);
|
|
22
|
-
response["type"] = "card_gen";
|
|
21
|
+
// console.log("response to card generation ", response);
|
|
22
|
+
response["type"] = isGapFill ? "gap_fill" : "card_gen";
|
|
23
23
|
response.metadata = {
|
|
24
24
|
"req_time": response.generated_at,
|
|
25
25
|
"req_type": response.type,
|
|
@@ -42,25 +42,28 @@ class GenerateCards {
|
|
|
42
42
|
const missing_concepts = generatedData.generated_content.missing_concepts;
|
|
43
43
|
const missing_facts = generatedData.generated_content.missing_facts;
|
|
44
44
|
const unparsedTestCards = generatedData.generated_content.test_cards;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
45
|
+
const type = generatedData.type;
|
|
46
|
+
if (unparsedTestCards !== undefined && unparsedTestCards.length != 0) {
|
|
47
|
+
for (let elem of unparsedTestCards) {
|
|
48
|
+
if (elem.type == "flash") {
|
|
49
|
+
cardData.push(this.parseFlashCard(elem));
|
|
50
|
+
}
|
|
51
|
+
else if (elem.type == "mcq") {
|
|
52
|
+
cardData.push(this.parseMcqCard(elem));
|
|
53
|
+
}
|
|
54
|
+
else if (elem.type == "cloze") {
|
|
55
|
+
cardData.push(this.parseClozeCard(elem));
|
|
56
|
+
}
|
|
57
|
+
else if (elem.type == "match") {
|
|
58
|
+
cardData.push(this.parseMatchCard(elem));
|
|
59
|
+
}
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
usage_data["created_at"] = created_at;
|
|
60
|
-
usage_data["type"] = "card_gen";
|
|
61
63
|
return {
|
|
62
64
|
status_code: status_code,
|
|
63
65
|
metadata: usage_data,
|
|
66
|
+
type: type,
|
|
64
67
|
missing_concepts: missing_concepts,
|
|
65
68
|
missing_facts: missing_facts,
|
|
66
69
|
cards_data: cardData,
|
|
@@ -27,7 +27,7 @@ json
|
|
|
27
27
|
{
|
|
28
28
|
"type": "flash" | "mcq" | "cloze" | "match",
|
|
29
29
|
"card_content": { "front": "...", "back": "..." | "prompt": "...", "choices": [ ... ] | "prompt": "...", "options": [ ... ] | "right_choice 1": "...", "left_choice 1": "..." },
|
|
30
|
-
"card_reference": "
|
|
30
|
+
"card_reference": "heading",
|
|
31
31
|
"concepts": ["Concept1", "Concept2", "..."],
|
|
32
32
|
"facts": ["Fact1", "Fact2", "..."]
|
|
33
33
|
}
|
|
@@ -35,11 +35,10 @@ json
|
|
|
35
35
|
|
|
36
36
|
**Criteria**
|
|
37
37
|
• Each test card must include at least one concept or fact.
|
|
38
|
-
•
|
|
38
|
+
• Flashcards must not exceed 15% of the total number of cards.
|
|
39
39
|
• Each concept and fact must have at least one test card.
|
|
40
40
|
|
|
41
41
|
Further instructions are provided below.
|
|
42
|
-
|
|
43
42
|
Concepts are fundamental ideas that form the basis of knowledge in any discipline. They help organize and explain information, making it accessible and relatable.
|
|
44
43
|
|
|
45
44
|
You are provided with a list of identified concepts. Review this list and the content to determine if any concepts are missing.
|
|
@@ -67,7 +66,7 @@ json
|
|
|
67
66
|
{
|
|
68
67
|
"missing_facts": ["fact1", "fact2", "fact3", "..."]
|
|
69
68
|
}
|
|
70
|
-
|
|
69
|
+
After you have the complete list of concepts and facts, including any missing ones you identified, proceed to generate test cards for each.
|
|
71
70
|
|
|
72
71
|
1. Clarity: Ensure the test content is clear and unambiguous.
|
|
73
72
|
2. Specificity: Be specific about what you are asking. Avoid vague or overly broad questions or prompts.
|
|
@@ -77,23 +76,29 @@ json
|
|
|
77
76
|
Test cards must be one of the following types:
|
|
78
77
|
|
|
79
78
|
1. Flashcards: Have a front and back.
|
|
79
|
+
2. A flashcard consists of two sides: a front and a back. Both the front and back text content must not exceed more than 300 characters in length.
|
|
80
80
|
|
|
81
|
-
json
|
|
81
|
+
json schema for Flash Cards:
|
|
82
82
|
{
|
|
83
83
|
"type": "flash",
|
|
84
84
|
"card_content": {
|
|
85
|
-
"front": "<content for the front>",
|
|
86
|
-
"back": "<content for the back>"
|
|
85
|
+
"front": "<content for the front of the flashcard>",
|
|
86
|
+
"back": "<content for the back of the flashcard>"
|
|
87
87
|
},
|
|
88
|
-
"card_reference": "
|
|
88
|
+
"card_reference": "heading",
|
|
89
89
|
"concepts": ["Concept1", "Concept2", "..."],
|
|
90
90
|
"facts": ["Fact1", "Fact2", "..."]
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
2. Multiple Choice Questions (MCQ): Provide multiple choices to pick from. One or more should be correct.
|
|
95
|
+
• Minimum choices required: 2
|
|
96
|
+
• Maximum choices allowed: 8
|
|
97
|
+
• Minimum correct choices required: 1
|
|
98
|
+
• Maximum character length for the prompt: 320
|
|
99
|
+
• Maximum character length for each choice: 42
|
|
95
100
|
|
|
96
|
-
json
|
|
101
|
+
json schema for mcqs
|
|
97
102
|
{
|
|
98
103
|
"type": "mcq",
|
|
99
104
|
"card_content": {
|
|
@@ -104,156 +109,55 @@ json
|
|
|
104
109
|
"... up to 8 choices"
|
|
105
110
|
]
|
|
106
111
|
},
|
|
107
|
-
"card_reference": "
|
|
112
|
+
"card_reference": "heading",
|
|
108
113
|
"concepts": ["Concept1", "Concept2", "..."],
|
|
109
114
|
"facts": ["Fact1", "Fact2", "..."]
|
|
110
115
|
}
|
|
111
116
|
|
|
117
|
+
3. Cloze:
|
|
118
|
+
Fill-in-the-blank style test card. Use double curly braces {{}} to indicate a cloze this is absolute necessagr
|
|
112
119
|
• Minimum choices required: 2
|
|
113
120
|
• Maximum choices allowed: 8
|
|
114
121
|
• Minimum correct choices required: 1
|
|
115
122
|
• Maximum character length for the prompt: 320
|
|
116
|
-
• Maximum character length for
|
|
117
|
-
|
|
118
|
-
3. Cloze: Fill-in-the-blank style test card. Use double curly braces {{}} to indicate a cloze.
|
|
123
|
+
• Maximum character length for an individual cloze: 90
|
|
119
124
|
|
|
120
|
-
json
|
|
125
|
+
json schema for cloze
|
|
121
126
|
{
|
|
122
127
|
"type": "cloze",
|
|
123
|
-
"card_content":{
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
{"option"
|
|
127
|
-
{"option"
|
|
128
|
-
{"option"
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
"card_content": {
|
|
129
|
+
"text": "Accidentals in music denote {{c0:notes}} that do not belong to the {{c1:scale}} or {{c2:mode}} indicated by the key signature.",
|
|
130
|
+
"options": [
|
|
131
|
+
{"option": "notes", "cloze": "c0"},
|
|
132
|
+
{"option": "scale", "cloze": "c1"},
|
|
133
|
+
{"option": "mode", "cloze": "c2"},
|
|
134
|
+
{"option": "chords", "cloze": null},
|
|
135
|
+
"... up to 8 choices"
|
|
131
136
|
]
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
"card_reference": "source_title#heading",
|
|
137
|
+
},
|
|
138
|
+
"card_reference": "heading",
|
|
135
139
|
"concepts": ["Concept1", "Concept2", "..."],
|
|
136
140
|
"facts": ["Fact1", "Fact2", "..."]
|
|
137
141
|
}
|
|
138
142
|
|
|
139
|
-
|
|
140
|
-
• Maximum choices allowed: 8
|
|
141
|
-
• Minimum correct choices required: 1
|
|
142
|
-
• Maximum character length for the prompt: 320
|
|
143
|
-
• Maximum character length for an individual cloze: 90
|
|
143
|
+
|
|
144
144
|
|
|
145
145
|
4. Match: Pairing items.
|
|
146
|
+
• Maximum character length for each item in a pair: 42
|
|
146
147
|
|
|
147
|
-
json
|
|
148
|
+
json schema for match
|
|
148
149
|
{
|
|
149
150
|
"type": "match",
|
|
150
151
|
"card_content": {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
"
|
|
156
|
-
}
|
|
157
|
-
"card_reference": "source_title#heading",
|
|
152
|
+
"right_choice 1": "left_choice 1",
|
|
153
|
+
"right_choice 2": "left_choice 2",
|
|
154
|
+
"... up to 8 total pairs"
|
|
155
|
+
},
|
|
156
|
+
"card_reference": "heading",
|
|
158
157
|
"concepts": ["Concept1", "Concept2", "..."],
|
|
159
158
|
"facts": ["Fact1", "Fact2", "..."]
|
|
160
159
|
}
|
|
161
160
|
|
|
162
|
-
• Maximum character length for each item in a pair: 42
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
The schema for each card type is below.
|
|
166
|
-
|
|
167
|
-
A flashcard consists of two sides: a front and a back. Both the front and back text content must not exceed more than 300 characters in length.
|
|
168
|
-
|
|
169
|
-
The content schema should be represented in this manner:
|
|
170
|
-
json
|
|
171
|
-
{
|
|
172
|
-
"front": "<content for the front of the flashcard>",
|
|
173
|
-
"back": "<content for the back of the flashcard>"
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
The schema for an mcq card is shown below.
|
|
178
|
-
|
|
179
|
-
json
|
|
180
|
-
{
|
|
181
|
-
"prompt": "<question text>",
|
|
182
|
-
"choices":
|
|
183
|
-
[
|
|
184
|
-
{
|
|
185
|
-
choice: "choice 1",
|
|
186
|
-
is_correct: true or false
|
|
187
|
-
},
|
|
188
|
-
{
|
|
189
|
-
choice: "choice 2",
|
|
190
|
-
is_correct: true or false
|
|
191
|
-
}
|
|
192
|
-
"... up to 8 choices"
|
|
193
|
-
]
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
Minimum choices required: 2
|
|
197
|
-
Maximum choices allowed: 8
|
|
198
|
-
Minimum correct choices required: 1
|
|
199
|
-
Maximum character length for the prompt: 320
|
|
200
|
-
Maximum character length for each choice: 42
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
For questions of the "type": "cloze", which refers to a fill-in-the-blank style question, the format is outlined below. I have used the sample text here because it is easier to illustrate the schema with an example:
|
|
204
|
-
|
|
205
|
-
json
|
|
206
|
-
{
|
|
207
|
-
"prompt": "Accidentals in music denote {{c0:notes}} that do not belong to the {{c1:scale}} or {{c2:mode}} indicated by the key signature."
|
|
208
|
-
"options":
|
|
209
|
-
[
|
|
210
|
-
{
|
|
211
|
-
"option: "notes",
|
|
212
|
-
"cloze": "c0"
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
"option: "chords",
|
|
216
|
-
"cloze": null
|
|
217
|
-
},
|
|
218
|
-
{
|
|
219
|
-
"option: "scale",
|
|
220
|
-
"cloze": "c1"
|
|
221
|
-
},
|
|
222
|
-
{
|
|
223
|
-
"option: "mode",
|
|
224
|
-
"cloze": "c2"
|
|
225
|
-
},
|
|
226
|
-
|
|
227
|
-
{
|
|
228
|
-
"option: "tilda",
|
|
229
|
-
"cloze": null
|
|
230
|
-
},
|
|
231
|
-
{
|
|
232
|
-
"option: "score",
|
|
233
|
-
"cloze": null
|
|
234
|
-
},
|
|
235
|
-
"... up to a maximum of 8 choices total"
|
|
236
|
-
]
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
Minimum choices required: 2
|
|
240
|
-
Maximum choices allowed: 8
|
|
241
|
-
Minimum correct choices required: 1
|
|
242
|
-
Maximum character length for the prompt: 320
|
|
243
|
-
Maximum character length for an individual cloze: 90
|
|
244
|
-
|
|
245
|
-
The schema for match type cards are as follows.
|
|
246
|
-
json
|
|
247
|
-
{
|
|
248
|
-
"<left_text1>": "<right_text1>",
|
|
249
|
-
"<left_text2>": "<right_text2>",
|
|
250
|
-
"<left_text3>": "<right_text3>",
|
|
251
|
-
...
|
|
252
|
-
"<left_text8>": "<right_text8>"
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
Maximum character length for each item in a pair: 42
|
|
256
|
-
Each test card needs a reference. A reference can either be the entire source or a specific heading in the source. Whenever possible, pick a main heading to direct the user to the most relevant part of the source material. The reference schema is as follows: source_title#main_heading, where #main_heading is optional.
|
|
257
161
|
Once you are done generating the test cards. Go back and evaulate the full list of concepts and fact that include any of the missing concepts or facts along with the list that was provided as the input.
|
|
258
162
|
|
|
259
163
|
Are there any concept or fact that don't have a test card yet? If yes, go back and create one.
|
|
@@ -267,7 +171,6 @@ Once you are done generating the test cards, review the full list of concepts an
|
|
|
267
171
|
3. Repeat this step until all concepts and facts are covered.
|
|
268
172
|
|
|
269
173
|
Only stop generating test questions once you believe there is sufficient testing material for learners to fully understand the concepts and remember the facts. The same concept or fact can have multiple test cards, so continue creating test cards until you are confident that there are enough for learners to fully grasp the source material.
|
|
270
|
-
|
|
271
174
|
`;
|
|
272
175
|
function returnCardGenPrompt() {
|
|
273
176
|
return promptString;
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.OnlyEverGenerator = void 0;
|
|
4
2
|
// import express from "express";
|
|
5
3
|
// import { returnCardGenPrompt } from "./constants/prompts/card_gen_prompt";
|
|
6
4
|
// import { returnTypologyPrompt } from "./constants/prompts/typology_prompt";
|
|
7
5
|
// import { GenerateArgs } from "./utils/generate_args";
|
|
8
6
|
// import { returnFields, returnHeadings, returnSourceData } from "./constants/source_data";
|
|
7
|
+
// import config from "./config";
|
|
8
|
+
// const app = express();
|
|
9
|
+
// const port = 3000;
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.OnlyEverGenerator = void 0;
|
|
9
12
|
const app_1 = require("./bootstrap/app");
|
|
10
13
|
Object.defineProperty(exports, "OnlyEverGenerator", { enumerable: true, get: function () { return app_1.OnlyEverGenerator; } });
|
|
11
14
|
/// All the Codes Below uses express and are strictly for development purpose, while publishing the package, comment everything
|
|
@@ -22,7 +25,7 @@ Object.defineProperty(exports, "OnlyEverGenerator", { enumerable: true, get: fun
|
|
|
22
25
|
// let content = returnSourceData().toString()
|
|
23
26
|
// let headings = returnHeadings();
|
|
24
27
|
// // let aiRequest = await openAIRequest(prompt,content);
|
|
25
|
-
// let aiRequest = await oeGen.generateCard(prompt,content);
|
|
28
|
+
// let aiRequest = await oeGen.generateCard(prompt,content, false);
|
|
26
29
|
// res.send(aiRequest);
|
|
27
30
|
// });
|
|
28
31
|
// app.get('/typology', async(req,res)=>{
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "only_ever_generator",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"start": "nodemon dist/index.js",
|
|
6
|
+
"start": "npm run build && nodemon dist/index.js",
|
|
7
7
|
"build": "tsc",
|
|
8
8
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
9
|
},
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"axios": "^1.7.2",
|
|
22
22
|
"dotenv": "^16.4.5",
|
|
23
23
|
"express": "^4.19.2"
|
|
24
|
+
|
|
24
25
|
},
|
|
25
26
|
"eslintConfig": {
|
|
26
27
|
"parser": "typescript-eslint-parser",
|
package/src/bootstrap/app.ts
CHANGED
|
@@ -8,81 +8,152 @@ import { GenerateArgs } from "../utils/generate_args";
|
|
|
8
8
|
import { returnFields } from "../constants/source_data";
|
|
9
9
|
import { returnTypologyData } from "../parse/response_format_typology";
|
|
10
10
|
|
|
11
|
+
function isEmpty(obj: object): boolean {
|
|
12
|
+
return Object.keys(obj).length === 0;
|
|
13
|
+
}
|
|
14
|
+
/// OnlyEverGenerator
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
export class OnlyEverGenerator {
|
|
17
|
+
public api_key: string = "";
|
|
18
|
+
public openAiService: OpenAiService;
|
|
19
|
+
parsedContent: string = "";
|
|
20
|
+
expectedFields: Array<string>;
|
|
21
|
+
constructor(
|
|
22
|
+
apiKey: string,
|
|
23
|
+
model: string,
|
|
24
|
+
content: Array<any>,
|
|
25
|
+
expected_fields: Array<string>
|
|
26
|
+
) {
|
|
27
|
+
this.api_key = apiKey;
|
|
28
|
+
this.openAiService = new OpenAiService(
|
|
29
|
+
apiKey,
|
|
30
|
+
model ?? "gpt-3.5-turbo-1106"
|
|
31
|
+
);
|
|
32
|
+
this.parsedContent = new ParseSourceContent(content).parse();
|
|
33
|
+
this.expectedFields = returnFields();
|
|
34
|
+
}
|
|
13
35
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
expectedFields: Array<string>
|
|
19
|
-
constructor(apiKey:string, model: string, content: Array<any>, expected_fields: Array<string>){
|
|
20
|
-
this.api_key = apiKey;
|
|
21
|
-
this.openAiService = new OpenAiService(apiKey,model ?? 'gpt-3.5-turbo-1106');
|
|
22
|
-
this.parsedContent = new ParseSourceContent(content).parse();
|
|
23
|
-
this.expectedFields = returnFields()
|
|
24
|
-
};
|
|
36
|
+
typologyResponse: any = {};
|
|
37
|
+
cardgenResponse: any = {};
|
|
38
|
+
summarizeResponse = {};
|
|
39
|
+
gapFillResponse: any = {};
|
|
25
40
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
41
|
+
async generate(
|
|
42
|
+
generate_typology: boolean = false,
|
|
43
|
+
generate_card: boolean = false
|
|
44
|
+
): Promise<Array<any>> {
|
|
45
|
+
let typologyPrompt = returnTypologyPrompt();
|
|
46
|
+
let cardPrompt = returnCardGenPrompt();
|
|
47
|
+
let args = new GenerateArgs(generate_card, generate_typology, false, {
|
|
48
|
+
typology_prompt: typologyPrompt,
|
|
49
|
+
card_gen_prompt: cardPrompt,
|
|
50
|
+
summary_prompt: "",
|
|
51
|
+
});
|
|
52
|
+
const responseToReturn = [];
|
|
53
|
+
const whatNeedsToBeGenerated = args.getWhatNeedsToBeGenerated();
|
|
54
|
+
for (let elem of whatNeedsToBeGenerated)
|
|
55
|
+
if (elem == "generate_tyopology") {
|
|
56
|
+
this.typologyResponse = await this.generateTypology(
|
|
57
|
+
args.prompts.typology_prompt ?? ""
|
|
58
|
+
);
|
|
59
|
+
responseToReturn.push(this.typologyResponse);
|
|
60
|
+
} else if (elem == "generate_card") {
|
|
61
|
+
this.cardgenResponse = await this.generateCard(
|
|
62
|
+
args.prompts.card_gen_prompt ?? "",
|
|
63
|
+
this.parsedContent + JSON.stringify(this.typologyResponse),
|
|
64
|
+
false
|
|
65
|
+
);
|
|
66
|
+
responseToReturn.push(this.cardgenResponse);
|
|
67
|
+
}
|
|
68
|
+
if (this.cardgenResponse.status_code == 200) {
|
|
69
|
+
let gapFill = this.gapFilling();
|
|
70
|
+
if (
|
|
71
|
+
gapFill.remainingConcepts.length !== 0 ||
|
|
72
|
+
gapFill.remainingFacts.length !== 0
|
|
73
|
+
) {
|
|
74
|
+
this.gapFillResponse = await this.generateCard(
|
|
75
|
+
args.prompts.card_gen_prompt ?? "",
|
|
76
|
+
this.parsedContent +
|
|
77
|
+
"Generate cards only suitable for the given remaining concepts and facts" +
|
|
78
|
+
JSON.stringify(gapFill) +
|
|
79
|
+
"Exclude generating these cards" +
|
|
80
|
+
JSON.stringify(this.cardgenResponse.cards_data),
|
|
81
|
+
true
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
responseToReturn.push(this.gapFillResponse);
|
|
85
|
+
}
|
|
29
86
|
|
|
30
|
-
|
|
31
|
-
|
|
87
|
+
return responseToReturn;
|
|
88
|
+
}
|
|
32
89
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
): Promise<Array<any>> {
|
|
37
|
-
let typologyPrompt = returnTypologyPrompt();
|
|
38
|
-
let cardPrompt = returnCardGenPrompt();
|
|
39
|
-
let args = new GenerateArgs(
|
|
40
|
-
generate_card,
|
|
41
|
-
generate_typology,
|
|
42
|
-
false,
|
|
43
|
-
{
|
|
44
|
-
typology_prompt: typologyPrompt,
|
|
45
|
-
card_gen_prompt: cardPrompt,
|
|
46
|
-
summary_prompt: ''
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
);
|
|
50
|
-
const responseToReturn = [];
|
|
51
|
-
const whatNeedsToBeGenerated = args.getWhatNeedsToBeGenerated();
|
|
52
|
-
for(let elem of whatNeedsToBeGenerated)
|
|
53
|
-
if(elem == 'generate_tyopology'){
|
|
54
|
-
this.typologyResponse = await this.generateTypology(args.prompts.typology_prompt ?? '');
|
|
55
|
-
responseToReturn.push(this.typologyResponse);
|
|
56
|
-
}else if(elem == 'generate_card'){
|
|
57
|
-
this.cardgenResponse = await this.generateCard(args.prompts.card_gen_prompt ?? '', this.parsedContent + JSON.stringify(this.typologyResponse));
|
|
58
|
-
responseToReturn.push(this.cardgenResponse);
|
|
59
|
-
}
|
|
90
|
+
_returnParsedContent() {
|
|
91
|
+
return this.parsedContent;
|
|
92
|
+
}
|
|
60
93
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
94
|
+
async generateCard(prompt: string, content: string, isGapFill: boolean) {
|
|
95
|
+
let generateCards = new GenerateCards(this.openAiService);
|
|
96
|
+
let cardgenResponse = await generateCards.generateCards(
|
|
97
|
+
prompt ?? "",
|
|
98
|
+
content,
|
|
99
|
+
isGapFill
|
|
100
|
+
);
|
|
101
|
+
// let response = await this.openAiService?.sendRequest(prompt,this.parsedContent);
|
|
102
|
+
// response['type'] = 'card_gen';
|
|
103
|
+
return cardgenResponse;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async generateTypology(prompt: string) {
|
|
107
|
+
let response = await new GenerateTypology(
|
|
108
|
+
this.openAiService,
|
|
109
|
+
prompt,
|
|
110
|
+
this.parsedContent,
|
|
111
|
+
this.expectedFields
|
|
112
|
+
).generate();
|
|
113
|
+
return response;
|
|
114
|
+
}
|
|
68
115
|
|
|
116
|
+
gapFilling() {
|
|
117
|
+
let allConcepts: string[] = [];
|
|
118
|
+
let allFacts: string[] = [];
|
|
119
|
+
let generatedConceptsList: string[] = [];
|
|
120
|
+
let generatedFactsList: string[] = [];
|
|
121
|
+
if (!isEmpty(this.typologyResponse)) {
|
|
122
|
+
allConcepts.push(...(this.typologyResponse.concepts ?? []));
|
|
123
|
+
allFacts.push(...(this.typologyResponse?.facts ?? []));
|
|
124
|
+
}
|
|
69
125
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// let response = await this.openAiService?.sendRequest(prompt,this.parsedContent);
|
|
74
|
-
// response['type'] = 'card_gen';
|
|
75
|
-
return cardgenResponse;
|
|
126
|
+
if (!isEmpty(this.cardgenResponse)) {
|
|
127
|
+
allConcepts.push(...(this.cardgenResponse.missing_concepts ?? []));
|
|
128
|
+
allFacts.push(...(this.cardgenResponse.missing_facts ?? []));
|
|
76
129
|
}
|
|
77
130
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return response;
|
|
131
|
+
for (let card of this.cardgenResponse.cards_data) {
|
|
132
|
+
if (card.concepts.length != 0) {
|
|
133
|
+
generatedConceptsList.push(...card.concepts);
|
|
134
|
+
}
|
|
135
|
+
if (card.facts.length != 0) {
|
|
136
|
+
generatedFactsList.push(...card.facts);
|
|
137
|
+
}
|
|
86
138
|
}
|
|
87
|
-
|
|
88
|
-
|
|
139
|
+
|
|
140
|
+
let generatedConceptsSet = Array.from(new Set(generatedConceptsList));
|
|
141
|
+
let generatedFactsSet = Array.from(new Set(generatedFactsList));
|
|
142
|
+
|
|
143
|
+
let remainingConcepts: string[] = allConcepts.filter(
|
|
144
|
+
(item) => !generatedConceptsSet.includes(item)
|
|
145
|
+
);
|
|
146
|
+
let remainingFacts: string[] = allFacts.filter(
|
|
147
|
+
(item) => !generatedFactsSet.includes(item)
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
// allConcepts: allConcepts,
|
|
152
|
+
// allFacts: allFacts,
|
|
153
|
+
// generatedConcepts: generatedConceptsSet,
|
|
154
|
+
// generatedFacts: generatedFactsSet,
|
|
155
|
+
remainingConcepts: remainingConcepts,
|
|
156
|
+
remainingFacts: remainingFacts,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -6,10 +6,10 @@ export class GenerateCards {
|
|
|
6
6
|
this.openAiService = openAiService;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
async generateCards(prompt: string, parsedContent: string) {
|
|
9
|
+
async generateCards(prompt: string, parsedContent: string, isGapFill: boolean) {
|
|
10
10
|
let response = await this.openAiService?.sendRequest(prompt, parsedContent);
|
|
11
|
-
|
|
12
|
-
response["type"] = "card_gen";
|
|
11
|
+
// console.log("response to card generation ", response);
|
|
12
|
+
response["type"] = isGapFill ? "gap_fill":"card_gen";
|
|
13
13
|
response.metadata = {
|
|
14
14
|
"req_time": response.generated_at,
|
|
15
15
|
"req_type": response.type,
|
|
@@ -31,24 +31,27 @@ export class GenerateCards {
|
|
|
31
31
|
const missing_concepts = generatedData.generated_content.missing_concepts;
|
|
32
32
|
const missing_facts = generatedData.generated_content.missing_facts;
|
|
33
33
|
const unparsedTestCards = generatedData.generated_content.test_cards;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
const type = generatedData.type;
|
|
35
|
+
if(unparsedTestCards !== undefined && unparsedTestCards.length != 0) {
|
|
36
|
+
for (let elem of unparsedTestCards) {
|
|
37
|
+
if (elem.type == "flash") {
|
|
38
|
+
cardData.push(this.parseFlashCard(elem));
|
|
39
|
+
} else if (elem.type == "mcq") {
|
|
40
|
+
cardData.push(this.parseMcqCard(elem));
|
|
41
|
+
} else if (elem.type == "cloze") {
|
|
42
|
+
cardData.push(this.parseClozeCard(elem));
|
|
43
|
+
} else if (elem.type == "match") {
|
|
44
|
+
cardData.push(this.parseMatchCard(elem));
|
|
45
45
|
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
46
49
|
usage_data["created_at"] = created_at;
|
|
47
|
-
usage_data["type"] = "card_gen";
|
|
48
50
|
|
|
49
51
|
return {
|
|
50
52
|
status_code: status_code,
|
|
51
53
|
metadata: usage_data,
|
|
54
|
+
type: type,
|
|
52
55
|
missing_concepts: missing_concepts,
|
|
53
56
|
missing_facts: missing_facts,
|
|
54
57
|
cards_data: cardData,
|
|
@@ -24,7 +24,7 @@ json
|
|
|
24
24
|
{
|
|
25
25
|
"type": "flash" | "mcq" | "cloze" | "match",
|
|
26
26
|
"card_content": { "front": "...", "back": "..." | "prompt": "...", "choices": [ ... ] | "prompt": "...", "options": [ ... ] | "right_choice 1": "...", "left_choice 1": "..." },
|
|
27
|
-
"card_reference": "
|
|
27
|
+
"card_reference": "heading",
|
|
28
28
|
"concepts": ["Concept1", "Concept2", "..."],
|
|
29
29
|
"facts": ["Fact1", "Fact2", "..."]
|
|
30
30
|
}
|
|
@@ -32,11 +32,10 @@ json
|
|
|
32
32
|
|
|
33
33
|
**Criteria**
|
|
34
34
|
• Each test card must include at least one concept or fact.
|
|
35
|
-
•
|
|
35
|
+
• Flashcards must not exceed 15% of the total number of cards.
|
|
36
36
|
• Each concept and fact must have at least one test card.
|
|
37
37
|
|
|
38
38
|
Further instructions are provided below.
|
|
39
|
-
|
|
40
39
|
Concepts are fundamental ideas that form the basis of knowledge in any discipline. They help organize and explain information, making it accessible and relatable.
|
|
41
40
|
|
|
42
41
|
You are provided with a list of identified concepts. Review this list and the content to determine if any concepts are missing.
|
|
@@ -64,7 +63,7 @@ json
|
|
|
64
63
|
{
|
|
65
64
|
"missing_facts": ["fact1", "fact2", "fact3", "..."]
|
|
66
65
|
}
|
|
67
|
-
|
|
66
|
+
After you have the complete list of concepts and facts, including any missing ones you identified, proceed to generate test cards for each.
|
|
68
67
|
|
|
69
68
|
1. Clarity: Ensure the test content is clear and unambiguous.
|
|
70
69
|
2. Specificity: Be specific about what you are asking. Avoid vague or overly broad questions or prompts.
|
|
@@ -74,23 +73,29 @@ json
|
|
|
74
73
|
Test cards must be one of the following types:
|
|
75
74
|
|
|
76
75
|
1. Flashcards: Have a front and back.
|
|
76
|
+
2. A flashcard consists of two sides: a front and a back. Both the front and back text content must not exceed more than 300 characters in length.
|
|
77
77
|
|
|
78
|
-
json
|
|
78
|
+
json schema for Flash Cards:
|
|
79
79
|
{
|
|
80
80
|
"type": "flash",
|
|
81
81
|
"card_content": {
|
|
82
|
-
"front": "<content for the front>",
|
|
83
|
-
"back": "<content for the back>"
|
|
82
|
+
"front": "<content for the front of the flashcard>",
|
|
83
|
+
"back": "<content for the back of the flashcard>"
|
|
84
84
|
},
|
|
85
|
-
"card_reference": "
|
|
85
|
+
"card_reference": "heading",
|
|
86
86
|
"concepts": ["Concept1", "Concept2", "..."],
|
|
87
87
|
"facts": ["Fact1", "Fact2", "..."]
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
2. Multiple Choice Questions (MCQ): Provide multiple choices to pick from. One or more should be correct.
|
|
92
|
+
• Minimum choices required: 2
|
|
93
|
+
• Maximum choices allowed: 8
|
|
94
|
+
• Minimum correct choices required: 1
|
|
95
|
+
• Maximum character length for the prompt: 320
|
|
96
|
+
• Maximum character length for each choice: 42
|
|
92
97
|
|
|
93
|
-
json
|
|
98
|
+
json schema for mcqs
|
|
94
99
|
{
|
|
95
100
|
"type": "mcq",
|
|
96
101
|
"card_content": {
|
|
@@ -101,156 +106,55 @@ json
|
|
|
101
106
|
"... up to 8 choices"
|
|
102
107
|
]
|
|
103
108
|
},
|
|
104
|
-
"card_reference": "
|
|
109
|
+
"card_reference": "heading",
|
|
105
110
|
"concepts": ["Concept1", "Concept2", "..."],
|
|
106
111
|
"facts": ["Fact1", "Fact2", "..."]
|
|
107
112
|
}
|
|
108
113
|
|
|
114
|
+
3. Cloze:
|
|
115
|
+
Fill-in-the-blank style test card. Use double curly braces {{}} to indicate a cloze this is absolute necessagr
|
|
109
116
|
• Minimum choices required: 2
|
|
110
117
|
• Maximum choices allowed: 8
|
|
111
118
|
• Minimum correct choices required: 1
|
|
112
119
|
• Maximum character length for the prompt: 320
|
|
113
|
-
• Maximum character length for
|
|
114
|
-
|
|
115
|
-
3. Cloze: Fill-in-the-blank style test card. Use double curly braces {{}} to indicate a cloze.
|
|
120
|
+
• Maximum character length for an individual cloze: 90
|
|
116
121
|
|
|
117
|
-
json
|
|
122
|
+
json schema for cloze
|
|
118
123
|
{
|
|
119
124
|
"type": "cloze",
|
|
120
|
-
"card_content":{
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
{"option"
|
|
124
|
-
{"option"
|
|
125
|
-
{"option"
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
"card_content": {
|
|
126
|
+
"text": "Accidentals in music denote {{c0:notes}} that do not belong to the {{c1:scale}} or {{c2:mode}} indicated by the key signature.",
|
|
127
|
+
"options": [
|
|
128
|
+
{"option": "notes", "cloze": "c0"},
|
|
129
|
+
{"option": "scale", "cloze": "c1"},
|
|
130
|
+
{"option": "mode", "cloze": "c2"},
|
|
131
|
+
{"option": "chords", "cloze": null},
|
|
132
|
+
"... up to 8 choices"
|
|
128
133
|
]
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"card_reference": "source_title#heading",
|
|
134
|
+
},
|
|
135
|
+
"card_reference": "heading",
|
|
132
136
|
"concepts": ["Concept1", "Concept2", "..."],
|
|
133
137
|
"facts": ["Fact1", "Fact2", "..."]
|
|
134
138
|
}
|
|
135
139
|
|
|
136
|
-
|
|
137
|
-
• Maximum choices allowed: 8
|
|
138
|
-
• Minimum correct choices required: 1
|
|
139
|
-
• Maximum character length for the prompt: 320
|
|
140
|
-
• Maximum character length for an individual cloze: 90
|
|
140
|
+
|
|
141
141
|
|
|
142
142
|
4. Match: Pairing items.
|
|
143
|
+
• Maximum character length for each item in a pair: 42
|
|
143
144
|
|
|
144
|
-
json
|
|
145
|
+
json schema for match
|
|
145
146
|
{
|
|
146
147
|
"type": "match",
|
|
147
148
|
"card_content": {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
"
|
|
153
|
-
}
|
|
154
|
-
"card_reference": "source_title#heading",
|
|
149
|
+
"right_choice 1": "left_choice 1",
|
|
150
|
+
"right_choice 2": "left_choice 2",
|
|
151
|
+
"... up to 8 total pairs"
|
|
152
|
+
},
|
|
153
|
+
"card_reference": "heading",
|
|
155
154
|
"concepts": ["Concept1", "Concept2", "..."],
|
|
156
155
|
"facts": ["Fact1", "Fact2", "..."]
|
|
157
156
|
}
|
|
158
157
|
|
|
159
|
-
• Maximum character length for each item in a pair: 42
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
The schema for each card type is below.
|
|
163
|
-
|
|
164
|
-
A flashcard consists of two sides: a front and a back. Both the front and back text content must not exceed more than 300 characters in length.
|
|
165
|
-
|
|
166
|
-
The content schema should be represented in this manner:
|
|
167
|
-
json
|
|
168
|
-
{
|
|
169
|
-
"front": "<content for the front of the flashcard>",
|
|
170
|
-
"back": "<content for the back of the flashcard>"
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
The schema for an mcq card is shown below.
|
|
175
|
-
|
|
176
|
-
json
|
|
177
|
-
{
|
|
178
|
-
"prompt": "<question text>",
|
|
179
|
-
"choices":
|
|
180
|
-
[
|
|
181
|
-
{
|
|
182
|
-
choice: "choice 1",
|
|
183
|
-
is_correct: true or false
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
choice: "choice 2",
|
|
187
|
-
is_correct: true or false
|
|
188
|
-
}
|
|
189
|
-
"... up to 8 choices"
|
|
190
|
-
]
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
Minimum choices required: 2
|
|
194
|
-
Maximum choices allowed: 8
|
|
195
|
-
Minimum correct choices required: 1
|
|
196
|
-
Maximum character length for the prompt: 320
|
|
197
|
-
Maximum character length for each choice: 42
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
For questions of the "type": "cloze", which refers to a fill-in-the-blank style question, the format is outlined below. I have used the sample text here because it is easier to illustrate the schema with an example:
|
|
201
|
-
|
|
202
|
-
json
|
|
203
|
-
{
|
|
204
|
-
"prompt": "Accidentals in music denote {{c0:notes}} that do not belong to the {{c1:scale}} or {{c2:mode}} indicated by the key signature."
|
|
205
|
-
"options":
|
|
206
|
-
[
|
|
207
|
-
{
|
|
208
|
-
"option: "notes",
|
|
209
|
-
"cloze": "c0"
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
"option: "chords",
|
|
213
|
-
"cloze": null
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
"option: "scale",
|
|
217
|
-
"cloze": "c1"
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
"option: "mode",
|
|
221
|
-
"cloze": "c2"
|
|
222
|
-
},
|
|
223
|
-
|
|
224
|
-
{
|
|
225
|
-
"option: "tilda",
|
|
226
|
-
"cloze": null
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
"option: "score",
|
|
230
|
-
"cloze": null
|
|
231
|
-
},
|
|
232
|
-
"... up to a maximum of 8 choices total"
|
|
233
|
-
]
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
Minimum choices required: 2
|
|
237
|
-
Maximum choices allowed: 8
|
|
238
|
-
Minimum correct choices required: 1
|
|
239
|
-
Maximum character length for the prompt: 320
|
|
240
|
-
Maximum character length for an individual cloze: 90
|
|
241
|
-
|
|
242
|
-
The schema for match type cards are as follows.
|
|
243
|
-
json
|
|
244
|
-
{
|
|
245
|
-
"<left_text1>": "<right_text1>",
|
|
246
|
-
"<left_text2>": "<right_text2>",
|
|
247
|
-
"<left_text3>": "<right_text3>",
|
|
248
|
-
...
|
|
249
|
-
"<left_text8>": "<right_text8>"
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
Maximum character length for each item in a pair: 42
|
|
253
|
-
Each test card needs a reference. A reference can either be the entire source or a specific heading in the source. Whenever possible, pick a main heading to direct the user to the most relevant part of the source material. The reference schema is as follows: source_title#main_heading, where #main_heading is optional.
|
|
254
158
|
Once you are done generating the test cards. Go back and evaulate the full list of concepts and fact that include any of the missing concepts or facts along with the list that was provided as the input.
|
|
255
159
|
|
|
256
160
|
Are there any concept or fact that don't have a test card yet? If yes, go back and create one.
|
|
@@ -264,7 +168,6 @@ Once you are done generating the test cards, review the full list of concepts an
|
|
|
264
168
|
3. Repeat this step until all concepts and facts are covered.
|
|
265
169
|
|
|
266
170
|
Only stop generating test questions once you believe there is sufficient testing material for learners to fully understand the concepts and remember the facts. The same concept or fact can have multiple test cards, so continue creating test cards until you are confident that there are enough for learners to fully grasp the source material.
|
|
267
|
-
|
|
268
171
|
`;
|
|
269
172
|
|
|
270
173
|
|
package/src/index.ts
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
// import { returnTypologyPrompt } from "./constants/prompts/typology_prompt";
|
|
5
5
|
// import { GenerateArgs } from "./utils/generate_args";
|
|
6
6
|
// import { returnFields, returnHeadings, returnSourceData } from "./constants/source_data";
|
|
7
|
-
import { OnlyEverGenerator } from "./bootstrap/app";
|
|
8
7
|
// import config from "./config";
|
|
9
8
|
// const app = express();
|
|
10
9
|
// const port = 3000;
|
|
11
10
|
|
|
11
|
+
import { OnlyEverGenerator } from "./bootstrap/app";
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
/// While Publishing the package , and using this code as a separate npm module
|
|
@@ -34,7 +34,7 @@ export {OnlyEverGenerator};
|
|
|
34
34
|
// let content = returnSourceData().toString()
|
|
35
35
|
// let headings = returnHeadings();
|
|
36
36
|
// // let aiRequest = await openAIRequest(prompt,content);
|
|
37
|
-
// let aiRequest = await oeGen.generateCard(prompt,content);
|
|
37
|
+
// let aiRequest = await oeGen.generateCard(prompt,content, false);
|
|
38
38
|
// res.send(aiRequest);
|
|
39
39
|
// });
|
|
40
40
|
|