File size: 8,818 Bytes
4f9b34e
 
 
 
8a2f508
65dc236
4f9b34e
 
 
 
 
 
 
 
 
 
 
3b226aa
 
f69ed2e
9ae4837
 
 
 
 
 
 
 
b49f46b
 
 
 
9ae4837
 
 
 
 
4f9b34e
 
 
9ae4837
4f9b34e
 
 
 
f69ed2e
609654e
9ae4837
dd2524f
9ae4837
 
2b46c32
 
 
 
 
4f9b34e
 
9ae4837
2b46c32
 
 
 
 
b49f46b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f69ed2e
b49f46b
 
 
 
 
 
 
 
 
f69ed2e
609654e
f69ed2e
e0e56e1
b49f46b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5c2dde2
b49f46b
e0e56e1
b49f46b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
609654e
4f9b34e
 
 
609654e
 
 
4f9b34e
 
b49f46b
 
4f9b34e
609654e
65dc236
4f9b34e
 
 
 
 
 
c863eab
65dc236
9e54b07
609654e
c863eab
 
9e54b07
 
f69ed2e
609654e
 
 
 
 
f69ed2e
 
c863eab
 
4f9b34e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# This is an app that uses the OpenAI API and the Chat GPT 4 model.
# It generates Free Response Questions for students based on a Common Core Standard and Area of Interest
# It takes as input: (1) The common core standard to use, (2) The area of interest

import streamlit as st
import json

from langchain.chat_models import ChatOpenAI
from langchain.schema import (
    AIMessage,
    HumanMessage,
    SystemMessage
)



#App UI starts here
st.set_page_config(page_title="FRQ Generator", page_icon=":robot:")
st.header("FRQs using GPT-4")
st.subheader("IMPORTANT: Please wait 60-70 seconds between responses. Chat GPT takes time to think.")
header_text=str('''
                              Paste a JSON file here, with the following information:
1. The name of the common core standard, 
2. The student's area of interest. 

E.g. 
```
{
 "input":"frq-generator",
 "entries":[
	    {"cc-standard": "CCSS.ELA-LITERACY.W.4.9", "area-of-interest": "Baseball" },
	    {"cc-standard": "CCSS.ELA-LITERACY.W.5.8", "area-of-interest": "Hiking" }
    ]
}
```
                              ''')
st.markdown(header_text)

if "sessionMessages" not in st.session_state:
    st.session_state.sessionMessages = [
        SystemMessage(content = "You are a bot that generates 'free response questions' for assesing school students based on the input of a Common Core Standard, and area of interest.")
    ]


#Function to return the response
def generateQuestion(question):
    questionPassageJSON=""
    ccStandard = question['cc-standard']
    #st.session_state.sessionMessages.append(HumanMessage(content="Common Core standard is: {question[0]}, and the area of interest is: {question[1]}"))
    
    ## Ask the model to understand the common core standard specified
    st.session_state.sessionMessages.append(HumanMessage(content="Read the common core standard :"+ccStandard+" and summarize its key requirements for a student in 3 bullet points. what year grade is the above standard applicable to? Answer in simple one word. E.g. '4th grade',' or 'Kindergarten', or 'Nursery'.\
                                                         Also tell if the student needs to read a passage to complete an assessment related to this standard. \
                                                         Also tell if the student needs to independently research a topic to complete an assessment related to this standard. \
                                                         Also tell if the standard requires testing on a math problem. \
                                                         Return the result in JSON format, with keys including 'grade-level', 'standard-requirement', 'is-passage-required', 'is-research-required', 'is-math-problem'."))
    assistant_answer = chat(st.session_state.sessionMessages)
    st.session_state.sessionMessages.append(AIMessage(content=assistant_answer.content))

    passagePrompt="The area of interest to consider for the exercise is "+question['area-of-interest']+". "
    # Create a JSON Object out of the Chat response
    chatResponseDict = json.loads(assistant_answer.content)
    
    if (not chatResponseDict['is-math-problem']):
        allChecksPassed=False
        repCount =0;
        while not allChecksPassed and repCount<3:
            #If a passage is required, generate a 300 word passage, for the appropriate grade level.
            if (chatResponseDict['is-passage-required']):
                passagePrompt+="Generate a 300 word passage on the given area of interest. It should cover the key points being tested in the common core standard specified. It should draw on real life incidents. Make it about one particular incident that highlights various things about "+question['area-of-interest']+"."
            #If external research is required, inform the student what to do research on.
            if (chatResponseDict['is-research-required']):
                passagePrompt+="Also suggest what specific topic or idea the student can do external research on, to be able to answer questions related to the common core standard specified. Use language as if you are speaking to the student directly, in the formal tone of a teacher or examiner."
            
            passagePrompt+="Make sure any passage or topics generated are appropriate in terms of vocabulary and comprehensibility for grade "+chatResponseDict['grade-level']
            passagePrompt+="Return the response in JSON format."
            # Ask the model 
            st.session_state.sessionMessages.append(HumanMessage(content=passagePrompt))
            passage_and_research = chat(st.session_state.sessionMessages)
            st.session_state.sessionMessages.append(AIMessage(content=passage_and_research.content))

        
            # Based on the above generated passage and research topic, we will now generate 3 FRQs and their grading rubrics
            frqPrompt='Generate 3 questions based on the previously discussed common core standard, and the above generated passage. The answers should be available either in the above passage, or the student should be able to find them with easy web research.  Good questions have: introduction, context, and open-ended question. Remember, the student is in grade: '+chatResponseDict['grade-level']
            frqPrompt+='Generate a rubric for evaluating the student responses for the above questions. Return the result in JSON format. E.g. { "rubric":[{"question":"..text of the question", "rubric":".. text of the rubric"}] etc.'
            frqPrompt+='In the final response JSON, also incldue the passage and research JSONs created above.'
            # Ask the model 
            st.session_state.sessionMessages.append(HumanMessage(content=frqPrompt))
            question_and_rubric = chat(st.session_state.sessionMessages)
            st.session_state.sessionMessages.append(AIMessage(content=question_and_rubric.content))

            
            #questionPassageJSON=json.loads(question_and_rubric.content)
            

            ## Do the QC Step
            qcPrompt='For the JSON generated in the previous step, please evaluate for each question and rubric:\
                    - Does the FRQ have an introduction, context, and an open-ended question\
                    - Does the Rubric prescribe checking for things that can be found in the passage, or suggested research areas.\
                    \
                    Pass and Fail answers only.\
                    Return the response in JSON Form. E.g.:\
                    {\
                        "type-of-response":"quality control",\
                        "qc-for-each-question":[\
                            {"FRQ":"Pass", "Rubric":"Fail"}\
                        ]\
                    }'
            # Ask the model 
            st.session_state.sessionMessages.append(HumanMessage(content=qcPrompt))
            qcResponseJson = json.loads(chat(st.session_state.sessionMessages).content)

            ## Write QC results
            st.write(qcResponseJson)

            ## Qc Response doesn't need to into the session state
            # Create a Array of qcResponses, and loop through them
            qcResponseArray = qcResponseJson['qc-for-each-question']
            # If any of the QC checks have failed, we set allChecksPassed to False, and the while loop starts again.
            allChecksPassed=True
            for row in qcResponseArray:
                if (row["FRQ"]=="Fail" or row["Rubric"]=="Fail"):
                    allChecksPassed=False
            ## Increase the repCount - we break the While loop after 3 reps, because using GPT4 is expensive, and we don't want it to go into a never ending loop
            repCount+=1
            


            
            



    return question_and_rubric.content


#Gets the user input
def get_text(textAreaKey):
    input_text = st.text_area(label="Paste/Write here",key=textAreaKey)
    textAreaKey+=1
    return input_text

## Temperature kept at 0.9, so that generated passages and questions are not too similar to each other.
chat = ChatOpenAI(temperature=0.9, model_name="gpt-4")

user_input = get_text(1)



submit = st.button('Generate')  

#If generate button is clicked
if submit:
    # Create a dict object from the JSON input
    inputDict = json.loads(user_input)
    questionArray=inputDict['entries']
    responseArray=[]
    # iterate through the dict, and create a new dict with each response from the LLM
    responseDict=[]
    for row in questionArray:
        st.write(row)
        
        response = generateQuestion(row)
        responseArray.append(response)
    
    st.subheader("AI Generated Question & Rubric (Note - in a real world scenario, the rubric won't be shown to the student):")
    st.write(responseArray)