saattrupdan commited on
Commit
a715bd8
1 Parent(s): b3f873d

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +3 -3
  2. app.py +149 -0
  3. requirements.txt +78 -0
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
  title: Foqa Validation
3
- emoji: 📚
4
- colorFrom: red
5
- colorTo: red
6
  sdk: gradio
7
  sdk_version: 4.28.3
8
  app_file: app.py
 
1
  ---
2
  title: Foqa Validation
3
+ emoji:
4
+ colorFrom: yellow
5
+ colorTo: gray
6
  sdk: gradio
7
  sdk_version: 4.28.3
8
  app_file: app.py
app.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Gradio app to validate examples of the FoQA dataset."""
2
+
3
+ from functools import partial
4
+ import os
5
+ from typing import Generator
6
+ import gradio as gr
7
+ from datasets import Dataset, load_dataset
8
+ import logging
9
+ import pandas as pd
10
+ import os
11
+ from dotenv import load_dotenv
12
+
13
+ load_dotenv()
14
+
15
+ logging.basicConfig(level=logging.INFO)
16
+ logger = logging.getLogger("foqa")
17
+
18
+
19
+ # Load the FoQA dataset in the global scope, as it is used in multiple functions
20
+ foqa = load_dataset(
21
+ "alexandrainst/foqa", split="train", token=os.getenv("HF_HUB_TOKEN")
22
+ )
23
+ assert isinstance(foqa, Dataset)
24
+ df = foqa.to_pandas()
25
+ assert isinstance(df, pd.DataFrame)
26
+
27
+
28
+ def main():
29
+ def non_validated_samples() -> Generator[tuple[str, str, str], None, None]:
30
+ """Iterate over non-validated samples in the FoQA dataset.
31
+
32
+ Yields:
33
+ A tuple (idx, question, answer) of a non-validated sample.
34
+ """
35
+ for idx, sample in df.iterrows():
36
+ if sample.validation is None:
37
+ yield str(idx), sample.question, sample.answers["text"][0]
38
+
39
+ itr = non_validated_samples()
40
+ idx, question, answer = next(itr)
41
+
42
+ with gr.Blocks(theme="monochrome", title="FoQA validation") as demo:
43
+ gr.Markdown("""
44
+ # FoQA Validation
45
+
46
+ This app automatically fetches examples from the Faroese Question Answering
47
+ dataset (FoQA), allowing you to annotate whether the question and answer
48
+ are correct Faroese or not.
49
+ """)
50
+ with gr.Row():
51
+ with gr.Column():
52
+ gr.Markdown("### Sample ID")
53
+ idx_box = gr.Markdown(value=idx)
54
+ gr.Markdown("### Question")
55
+ question_box = gr.Markdown(value=question)
56
+ gr.Markdown("### Answer")
57
+ answer_box = gr.Markdown(value=answer)
58
+ with gr.Column():
59
+ correct_btn = gr.Button(value="Correct")
60
+ incorrect_btn = gr.Button(value="Incorrect")
61
+ save_results_btn = gr.Button(value="Save results")
62
+
63
+ correct_btn.click(
64
+ fn=partial(assign_correct, itr=itr),
65
+ inputs=[idx_box, question_box, answer_box],
66
+ outputs=[idx_box, question_box, answer_box],
67
+ )
68
+ incorrect_btn.click(
69
+ fn=partial(assign_incorrect, itr=itr),
70
+ inputs=[idx_box, question_box, answer_box],
71
+ outputs=[idx_box, question_box, answer_box],
72
+ )
73
+ save_results_btn.click(fn=partial(save_results))
74
+
75
+ auth = [
76
+ ("annika", os.environ["ANNIKA_PASSWORD"]),
77
+ ("admin", os.environ["ADMIN_PASSWORD"]),
78
+ ]
79
+
80
+ demo.launch(share=True, auth=auth)
81
+
82
+
83
+ def save_results() -> None:
84
+ """Update the FoQA dataset with the validation status of a sample."""
85
+ logger.info("Saving results...")
86
+ gr.Info(message="Saving results...")
87
+ Dataset.from_pandas(df, preserve_index=False).push_to_hub(
88
+ repo_id="alexandrainst/foqa", token=os.getenv("HF_HUB_TOKEN")
89
+ )
90
+ gr.Info(message="Saved results!")
91
+ logger.info("Saved results.")
92
+
93
+
94
+ def assign_correct(
95
+ idx: str, question: str, answer: str, itr: Generator
96
+ ) -> tuple[gr.Markdown, gr.Markdown, gr.Markdown]:
97
+ """Assign the question and answer as correct.
98
+
99
+ Args:
100
+ idx:
101
+ The index of the sample to be assigned as correct.
102
+ question:
103
+ The question to be assigned as correct.
104
+ answer:
105
+ The answer to be assigned as correct.
106
+ itr:
107
+ The iterator over non-validated samples.
108
+
109
+ Returns:
110
+ The updated textboxes.
111
+ """
112
+ gr.Info(message="Assigned sample as correct")
113
+ logger.info(f"Assigned sample as correct: {question} - {answer}")
114
+ df.iloc[int(idx)].validation = "correct"
115
+ idx, question, answer = next(itr)
116
+ return (
117
+ gr.Markdown(value=idx), gr.Markdown(value=question), gr.Markdown(value=answer)
118
+ )
119
+
120
+
121
+ def assign_incorrect(
122
+ idx: str, question: str, answer: str, itr: Generator
123
+ ) -> tuple[gr.Markdown, gr.Markdown, gr.Markdown]:
124
+ """Assign the question and answer as incorrect.
125
+
126
+ Args:
127
+ idx:
128
+ The index of the sample to be assigned as incorrect.
129
+ question:
130
+ The question to be assigned as incorrect.
131
+ answer:
132
+ The answer to be assigned as incorrect.
133
+ itr:
134
+ The iterator over non-validated samples.
135
+
136
+ Returns:
137
+ The updated textboxes.
138
+ """
139
+ gr.Info(message="Assigned sample as incorrect")
140
+ logger.info(f"Assigned sample as incorrect: {question} - {answer}")
141
+ df.iloc[int(idx)].validation = "incorrect"
142
+ idx, question, answer = next(itr)
143
+ return (
144
+ gr.Markdown(value=idx), gr.Markdown(value=question), gr.Markdown(value=answer)
145
+ )
146
+
147
+
148
+ if __name__ == "__main__":
149
+ main()
requirements.txt ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==23.2.1
2
+ aiohttp==3.9.5
3
+ aiosignal==1.3.1
4
+ altair==5.3.0
5
+ annotated-types==0.6.0
6
+ anyio==4.3.0
7
+ async-timeout==4.0.3
8
+ attrs==23.2.0
9
+ certifi==2024.2.2
10
+ charset-normalizer==3.3.2
11
+ click==8.1.7
12
+ contourpy==1.2.1
13
+ cycler==0.12.1
14
+ datasets==2.19.0
15
+ dill==0.3.8
16
+ exceptiongroup==1.2.1
17
+ fastapi==0.110.2
18
+ ffmpy==0.3.2
19
+ filelock==3.13.4
20
+ fonttools==4.51.0
21
+ frozenlist==1.4.1
22
+ fsspec==2024.3.1
23
+ gradio==4.28.3
24
+ gradio_client==0.16.0
25
+ h11==0.14.0
26
+ httpcore==1.0.5
27
+ httpx==0.27.0
28
+ huggingface-hub==0.22.2
29
+ idna==3.7
30
+ importlib_resources==6.4.0
31
+ Jinja2==3.1.3
32
+ jsonschema==4.21.1
33
+ jsonschema-specifications==2023.12.1
34
+ kiwisolver==1.4.5
35
+ markdown-it-py==3.0.0
36
+ MarkupSafe==2.1.5
37
+ matplotlib==3.8.4
38
+ mdurl==0.1.2
39
+ multidict==6.0.5
40
+ multiprocess==0.70.16
41
+ numpy==1.26.4
42
+ orjson==3.10.1
43
+ packaging==24.0
44
+ pandas==2.2.2
45
+ pillow==10.3.0
46
+ pyarrow==16.0.0
47
+ pyarrow-hotfix==0.6
48
+ pydantic==2.7.1
49
+ pydantic_core==2.18.2
50
+ pydub==0.25.1
51
+ Pygments==2.17.2
52
+ pyparsing==3.1.2
53
+ python-dateutil==2.9.0.post0
54
+ python-dotenv==1.0.1
55
+ python-multipart==0.0.9
56
+ pytz==2024.1
57
+ PyYAML==6.0.1
58
+ referencing==0.35.0
59
+ requests==2.31.0
60
+ rich==13.7.1
61
+ rpds-py==0.18.0
62
+ ruff==0.4.2
63
+ semantic-version==2.10.0
64
+ shellingham==1.5.4
65
+ six==1.16.0
66
+ sniffio==1.3.1
67
+ starlette==0.37.2
68
+ tomlkit==0.12.0
69
+ toolz==0.12.1
70
+ tqdm==4.66.2
71
+ typer==0.12.3
72
+ typing_extensions==4.11.0
73
+ tzdata==2024.1
74
+ urllib3==2.2.1
75
+ uvicorn==0.29.0
76
+ websockets==11.0.3
77
+ xxhash==3.4.1
78
+ yarl==1.9.4