File size: 11,719 Bytes
bf75d52
3603153
bf75d52
a425fa9
 
895a686
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3603153
895a686
 
 
 
 
 
 
 
a9fe74f
a425fa9
7b358db
a425fa9
 
2eb4cf2
7b358db
a425fa9
d919aa0
919be7b
fb39ca3
2eb4cf2
 
fb39ca3
c40bc82
 
 
09ff2ee
7b358db
 
 
 
 
 
a9fe74f
 
 
 
 
 
 
7b358db
919be7b
d919aa0
bf75d52
a9fe74f
 
d919aa0
 
 
 
7b358db
d919aa0
919be7b
d919aa0
 
5053d22
d919aa0
028b757
31d31bd
 
8f41051
80eb545
f408e8c
 
d919aa0
f4facc1
aa10998
f2c0ef6
80eb545
c40bc82
80eb545
c40bc82
80eb545
c40bc82
80eb545
5053d22
 
f4facc1
8ac2e2e
 
fb39ca3
8ac2e2e
fb39ca3
8ac2e2e
fb39ca3
8ac2e2e
f4facc1
 
 
 
 
d201c51
 
 
796ea23
 
 
 
7c3fd9a
e7103e4
 
2b0e5c7
e7103e4
 
796ea23
e7103e4
d201c51
 
796ea23
 
 
 
d201c51
796ea23
 
d201c51
1d3a96d
 
 
 
 
796ea23
d201c51
31d31bd
d919aa0
 
8ac2e2e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d919aa0
 
89443f0
a9fe74f
 
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
import gradio as gr
import os

# PERSISTENT DATA STORAGE: these are used to upload user responses to a dataset

import json
from datetime import datetime
from pathlib import Path
from uuid import uuid4 
from huggingface_hub import CommitScheduler

JSON_DATASET_DIR = Path("json_dataset")
JSON_DATASET_DIR.mkdir(parents=True, exist_ok=True)

JSON_DATASET_PATH = JSON_DATASET_DIR / f"train-{uuid4()}.json"

scheduler = CommitScheduler(
    repo_id="ebrowne/test-data",
    repo_type="dataset",
    folder_path=JSON_DATASET_DIR,
    path_in_repo="data",
    token = os.getenv("HF_TOKEN")
)

def save_json(score1, score2):
    with scheduler.lock:
        with JSON_DATASET_PATH.open("a") as f:
            json.dump({"relevance": score1, "novelty": score2, "datetime": datetime.now().isoformat()}, f)
            f.write("\n")

# READING EXISTING DATA: this is used to read questions

"""
from datasets import load_dataset
qa_data = load_dataset("ebrowne/test-data", data_files = "test.json")
q = qa_data["train"][0] # loaded question data
"""

# VARIABLES: will eventually be loaded with JSON from a dataset 

"""
question_text = q["prompt"] + " " + q["question"]
answers_text = [q["a"], q["b"], q["c"], q["d"]]
"""
question_text = "An act of Congress provides that \"no federal court shall order the implementation of a public school desegregation plan that would require the transportation of any student to a school other than the school closest or next closest to his place of residence.\" Which of the following is the strongest argument for the constitutionality of the act?"
answers_text = ["The Fourteenth Amendment authorizes Congress to define governmental conduct which violates the equal protection clause.", "Under Article III, Congress may restrict the jurisdiction of the federal courts.", "Transportation of students is subject to regulation by Congress because commerce is involved.", "Congress provides partial support for public education and is therefore entitled to establish conditions upon the expenditure of federal grants."]
answer_id = 1
passage_texts = ["The IDEA also requires states receiving federal funds to educate disabled children in the \"[l]east restrictive environment\" appropriate for each child. 20 U.S.C. § 1412(a)(5). The statute mandates at § 1412(a)(5)(A):", 
            "Under the current iteration of Arkansas' school choice law-the 2017 Act-a school that claims a conflict with participating in school choice must show that it is subject to an active and enforceable desegregation court order or plan that \"explicitly limits the transfer of students between school districts.\" Ark. Code Ann. § 6-18-1906(a)(2). Accordingly, for Junction City to receive an exemption from participating in school choice under the 2017 Act, it must show that it is subject to a desegregation order that explicitly bars \"inter-district\" student transfers.",
            "This is not to say that a school may unilaterally reject or revise a child's stay-put IEP-that would defang the stay-put requirement entirely. To the contrary, the Supreme Court has made clear that the IDEA \"strip[s] schools of the unilateral authority they had traditionally employed to exclude disabled students.\" Honig , 484 U.S. at 323, 108 S.Ct. 592 (emphasis omitted); see also Sch. Comm. of the Town of Burlington v. Dep't of Educ. , 471 U.S. 359, 373, 105 S.Ct. 1996, 85 L.Ed.2d 385 (1985). Courts should therefore view deviations from the IEP \"with a critical eye to ensure that motivations other than those compatible with the statute, such as bureaucratic inertia, are not driving the decision.\" John M. , 502 F.3d at 715. But context matters; for example, as a child moves \"from elementary school to middle school or from middle school to high school,\" not every change necessitated by a new educational environment will necessarily violate the IDEA. See id. at 714-15.",
            "Under § 79-209(2), all schools are required to have a policy that states the number of absences after which the school shall render services to address a student's barriers to attendance. Such services shall include, but not be limited to:",
            "To assure that children attending public schools obtain a high quality education, the legislature shall make adequate provision to ensure that ... there are a sufficient number of classrooms ....",
            "courts should not disturb a state's denial of IDEA reimbursement where the chief benefits of the chosen school are the kind of advantages that might be preferred by parents of any child, disabled or not. Rather, the unilateral private placement is only appropriate if it provides education instruction [specially ] designed to meet the unique needs of a handicapped child.",
            "It is also likely that residents of the States will attend out-of-state schools that invoke the Exemptions, and that such students will seek contraceptive services through programs in their home states, also giving rise to fiscal injuries to the States that only a nationwide injunction can remedy.",
            "Although state classifications based on alienage are generally suspect, a state may reserve a government position for citizens if it is related to self-governance, involves policymaking, or requires exercise of important discretionary power over citizens. In these cases, only a rationality test is used. A public school teacher at the primary and secondary school level performs an important governmental function (e.g., he influences students' attitudes about government, the political process, citizenship, etc.), and therefore the exclusion of aliens is rationally related to the state's interest in furthering educational goals. [Ambach v. Norwick (1979)]",
            "Passage 9",
            "Passage 10"]
generation_4 = "Here is a generation at 4 passages."
generation_6 = "Here is a generation at 6 passages."
generation_10 = "Here is a generation at 10 passages."
gold_passage = "GOLD PASSAGE"
step = 0

# BLOCKS: main user interface

user_id = "NO_ID"

with gr.Blocks() as user_eval:
    # Title text introducing study
    gr.Markdown("""
    # Legal Retriever Evaluation Study
    Score the passages based on the question and provided answer choices. 
    """)

    # Passages and user evaluations thereof
    with gr.Row(equal_height = False, visible = False) as evals:
        # Passage text
        with gr.Column(scale = 2) as passages:
            selection = gr.HTML("""
            <h2> Retrieved Passage </h2>
            <p> """ + passage_texts[0] + "</p>")
            line = gr.Markdown("---")
            # New answers is able to render the Q and A with formatting. It doesn't change the contents of the answers.
            new_answers = answers_text.copy()
            new_answers[answer_id] = "**" + answers_text[answer_id] + "** ✅"
            passage_display = gr.Markdown("""
            ## Question and Answer
            *""" + question_text + 
            """* \n
            + """ + new_answers[0] + 
            """ \n
            + """ + new_answers[1] + 
            """ \n
            + """ + new_answers[2] + 
            """ \n
            + """ + new_answers[3])

        # Scoring box
        with gr.Column(scale = 1) as scores_p:
            desc_0 = gr.Markdown("Does the passage describe **a legal rule?**")
            eval_0 = gr.Radio(["Yes", "No"], label = "Some passages in our dataset include background details or stories that don't contain any meaningful legal information.")
            desc_1 = gr.Markdown("How **relevant** is this passage to the question?")
            eval_1 = gr.Slider(1, 5, step = 0.5, label = "Does the passage discuss information related to the question?")
            desc_2 = gr.Markdown("How would you rate the passage's **quality** in terms of detail, clarity, and focus?")
            eval_2 = gr.Slider(1, 5, step = 0.5, label = "Is it comprehensible? Is it thorough? Can it stand on its own?")
            desc_3 = gr.Markdown("How effectively does the passage **lead you to the correct answer?**")
            eval_3 = gr.Slider(1, 5, step = 0.5, label = "All things considered, does this passage help a user answer the question correctly?")
            btn_p = gr.Button("Next")
        
        with gr.Column(scale = 1, visible = False) as scores_g: 
            satisfied = gr.Markdown("How satisfied are you by this answer?")
            eval_satisfied = gr.Slider(1, 5, step = 0.5, label = "Would someone answering the question find value in these responses?")
            btn_g = gr.Button("Next")
        
        def next_p(eval_1, eval_2, eval_3):
            global step
            step += 1
            print(eval_1 + eval_2 + eval_3)
            if step == len(passage_texts):
                collapsible_string = ""
                for i, passage in enumerate(passage_texts):
                    collapsible_string += """
                            <strong>Passage """ + str(i + 1) + """</strong>
                            <p> """ + passage + """ </p>
                            """
                return {
                    selection: gr.HTML(collapsible_string),
                    scores_p: gr.Column(visible = False),
                    scores_g: gr.Column(visible = True)
                }
            else:
                return {
                    selection: gr.HTML("""
                        <h2> Retrieved Passage </h2> <br />
                        """ + passage_texts[step])
                }
        
        def next_g(eval_satisfied): 
            print(eval_satisfied)
            return {
                selection: gr.Markdown("next summary")
            }

        btn_p.click(fn = next_p, inputs = [eval_1, eval_2, eval_3], outputs = [selection, scores_p, scores_g])
        btn_g.click(fn = next_g, inputs = [eval_satisfied], outputs = [selection])

    # Question and answering dynamics
    with gr.Row(equal_height = False, visible = False) as question:
        with gr.Column():
            gr.Markdown("---")
            gr.Markdown("**Question**")
            gr.Markdown(question_text)
            a = gr.Button(answers_text[0])
            b = gr.Button(answers_text[1])
            c = gr.Button(answers_text[2])
            d = gr.Button(answers_text[3])

            def answer():
                return {
                    question: gr.Row(visible = False),
                    evals: gr.Row(visible = True)
                }
            
            a.click(fn = answer, outputs = [question, evals])
            b.click(fn = answer, outputs = [question, evals])
            c.click(fn = answer, outputs = [question, evals])
            d.click(fn = answer, outputs = [question, evals])

    with gr.Row() as login:
        with gr.Column():
            gr.Markdown("---")
            gr.Markdown("# Enter email to start")
            gr.Markdown("Thank you so much for your participation in our study! Please enter your email — we're using it to keep track of which questions you've answered and which you haven't seen. Use the same email every time to keep your progress saved. :)")
            email = gr.Textbox("Email")
            s = gr.Button("Start!")
      
            def submit_email(email):
                global user_id
                user_id = email
                print(user_id)
                return {
                    question: gr.Row(visible = True),
                    login: gr.Row(visible = False)
                }
            
            s.click(fn = submit_email, inputs = [email], outputs = [question, login])

# Starts on question, switches to evaluation after the user answers
user_eval.launch()

# https://github.com/gradio-app/gradio/issues/5791