CoolFace
Apppublic

BtB-ExpC/Normal_MC

sourceHugging Faceupdated 3y agoView on Hugging Face
0likes
app.py288 linesDownload Raw Back to root
1import openai2import random3import gradio as gr4import os5 6 7openai.api_key = os.environ["OpenAPI_Key"]8 9manual = r"""Deze tool werkt met 2 soorten input:10 111.   Een leerdoel, zoals:12 13Het rechterventrikel wordt van bloed voorzien door de rechter coronairarterie (RCA).14 152.    De complete HTML-code van een opgave in de MES Editor, zoals:16 17Exercise body:18 19<mc:exercise xmlns:mc="http://www.expertcollege.com/mes/multiple-choice/exercise"><mc:question><![CDATA[Theorie:<br />Het rechterventrikel wordt van bloed voorzien door de rechter coronairarterie (RCA). Direct na het ontspringen uit de sinus aortae geeft de RCA twee takken af.<br /><br />Stelling:<br />Dit zijn onder andere de .....]]></mc:question><mc:choices><mc:choice id="1"><![CDATA[Ramus descendens posterior]]></mc:choice><mc:choice id="2"><![CDATA[Conus arterie]]></mc:choice><mc:choice id="3"><![CDATA[Beide bovenstaande]]></mc:choice><mc:choice id="4"><![CDATA[Geen van bovenstaande]]></mc:choice></mc:choices></mc:exercise>20Exercise key:21 22<mc:key xmlns:mc="http://www.expertcollege.com/mes/multiple-choice/key"><mc:correctanswer id="2"/><mc:defaultexplanation><mc:text><![CDATA[Dit zijn de conus arterie, die het uitstroomkanaal van het rechterventrikel (de conus van de arteria pulmonalis) van bloed voorziet en een tweede tak, die de sinusknoop van bloed voorziet.]]></mc:text></mc:defaultexplanation></mc:key>"""23 24# Define the messages for stepOne25UserPrompt1 = r"""Exercise body:26 27<mc:exercise xmlns:mc="http://www.expertcollege.com/mes/multiple-choice/exercise"><mc:question><![CDATA[Theorie:<br />Bij een tekort aan trombocyten (≤150×10<sup>9</sup>/L) spreek je over trombocytopenie.<br /><br />Stelling:<br />Een trombocytopenie ontstaat door .....]]></mc:question><mc:choices><mc:choice id="2"><![CDATA[Een verhoogde afbraak]]></mc:choice><mc:choice id="3"><![CDATA[Een inadequate productie]]></mc:choice><mc:choice id="4"><![CDATA[Beide bovenstaande]]></mc:choice><mc:choice id="5"><![CDATA[Geen van bovenstaande]]></mc:choice></mc:choices></mc:exercise>28Exercise key:29 30<mc:key xmlns:mc="http://www.expertcollege.com/mes/multiple-choice/key"><mc:correctanswer id="4"/><mc:defaultexplanation><mc:text><![CDATA[]]></mc:text></mc:defaultexplanation></mc:key>31"""32AssistantPrompt1 = r"""Trombocytopenie, een tekort aan trombocyten, ontstaat door: '''zowel een verhoogde afbraak als een inadequate productie'''."""33UserPrompt2 = r"""Exercise body:34 35<mc:exercise xmlns:mc="http://www.expertcollege.com/mes/multiple-choice/exercise"><mc:question><![CDATA[Stelling:<br />Het buitenste vlies van het pericard wordt het epicard genoemd.]]></mc:question><mc:choices><mc:choice id="1"><![CDATA[Deze stelling is correct]]></mc:choice><mc:choice id="2"><![CDATA[Deze stelling is niet correct]]></mc:choice></mc:choices></mc:exercise>36Exercise key:37 38<mc:key xmlns:mc="http://www.expertcollege.com/mes/multiple-choice/key"><mc:correctanswer id="2"/><mc:defaultexplanation><mc:text><![CDATA[Het pericard (hartzakje) bestaat uit twee vliezen, namelijk het binnenste vlies (viscerale pericard, ook wel het epicard) en het buitenste vlies (pariëtale pericard).]]></mc:text></mc:defaultexplanation></mc:key>39"""40AssistantPrompt2 = "Het buitenste vlies van het pericard wordt '''het pariëtale pericard''' genoemd."41UserPrompt3 = r"""Exercise body:42 43<mc:exercise xmlns:mc="http://www.expertcollege.com/mes/multiple-choice/exercise"><mc:question><![CDATA[Theorie:<br />Acute myocardiale ischemie kan optreden bij gebruik van amfetaminen, ecstasy of cocaïne.<br /><br />Vraag:<br />Waardoor treed in dit geval hypotensie op?]]></mc:question><mc:choices><mc:choice id="1"><![CDATA[Door een verhoogde productie van rode bloedcellen]]></mc:choice><mc:choice id="2"><![CDATA[Door de stimulatie van de afgifte van insuline]]></mc:choice><mc:choice id="3"><![CDATA[Beide bovenstaande]]></mc:choice><mc:choice id="4"><![CDATA[Geen van bovenstaande]]></mc:choice></mc:choices></mc:exercise>44Exercise key:45 46<mc:key xmlns:mc="http://www.expertcollege.com/mes/multiple-choice/key"><mc:correctanswer id="4"/><mc:defaultexplanation><mc:text><![CDATA[Extra info:<br />Hypotensie treedt in dit geval op door acute myocardiale depressie als gevolg van ischemie en een direct toxisch effect van het middel.]]></mc:text></mc:defaultexplanation></mc:key>47"""48AssistantPrompt3 = "In het geval van acute myocardiale ischemie door gebruik van amfetaminen, ecstasy of cocaïne, treedt hypotensie op door: '''acute myocardiale depressie als gevolg van ischemie en een direct toxisch effect van het middel'''."49 50 51# Define the messages for stepTwo52UserPrompt21 = "Kennisonderdeel: '''De arteria pulmonalis''' komt rechtstreeks uit het rechterventrikel."53AssistantPrompt21 = "Vraag: Welke slagader komt rechtstreeks uit het rechterventrikel?\nJuiste antwoord: De arteria pulmonalis"54UserPrompt22 = "Kennisonderdeel: Geografische kenmerken in een klantprofiel geven informatie over '''de woonplaats van een klant''', zoals het land, de regio of de stad."55AssistantPrompt22 = "Vraag: Waar geven geografische kenmerken in een klantprofiel informatie over?\nJuiste antwoord: De woonplaats van de klant"56 57# Define the messages for stepThree58SystemPrompt31 = r"""Je bent een breedgeschoolde professor met veel expertise over de onderwerpen van toetsvragen.59 60Genereer uitspraken die niet waar zijn, maar geloofwaardige misvattingen over de informatie in de gepresenteerde vraag.61 62Zorg ervoor dat alle misvattingen daadwerkelijk volledig onwaar zijn in alle gevallen en omstandigheden, maar op een subtiele manier. Ze moeten geloofwaardige variaties op het juiste antwoord presenteren. 63Formuleer je misvattingen overwegend positief, dus vermijd het gebruik van 'geen' en 'niet' en vermijd absoluut/extreem taalgebruik. Zorg dat het taalniveau overeenkomt met het juiste antwoord. 64Geef geen toelichting bij de misvattingen.65 66Let op: zorg dat je misvattingen:67    - zich strikt richten op de informatie in de vraag, niet op het overkoepelende onderwerp in zijn geheel68    - geloofwaardig zijn voor iemand met basiskennis over het studieonderwerp"""69UserPrompt31 = r"""Studieonderwerp: Het zenuwstelsel70Vraag: Wat maakt het zenuwstelsel onder andere mogelijk? 71Juiste antwoord: Eten, ademen, lopen, en praten"""72AssistantPrompt31 = r"""Misvattingen:731. Het zenuwstelsel is direct verantwoordelijk voor het opnemen van zuurstof uit de ingeademde lucht.742. Door het zenuwstelsel kunnen we energie maken uit zonlicht.753. Het zenuwstelsel maakt het mogelijk om vitamine B op te nemen uit zonlicht.764. Het zenuwstelsel maakt het mogelijk om het zuurstofniveau in het bloed te meten.775. Het regelen van de zuurstofbinding aan hemoglobine in de longen wordt mogelijk gemaakt door het zenuwstelsel.786. Het zenuwstelsel maakt het mogelijk om het suikergehalte in het bloed te regelen."""79UserPrompt32 = r"""Studieonderwerp: Het zenuwstelsel80Vraag: Wat zijn de twee voornaamste zenuwstelsels die we in het lichaam onderscheiden?81Juiste antwoord: Het centraal en perifeer zenuwstelsel"""82AssistantPrompt32 = r"""Misvattingen:831. In ons lichaam wordt het zenuwstelsel met name onderverdeeld in het autonome en het viscerale zenuwstelsel.842. We verdelen het zenuwstelsel in ons lichaam in de eerste plaats onder in het cerebrale en het spinale zenuwstelsel.853. In het menselijk lichaam worden voornamelijk twee zenuwstelsels onderscheiden: het animale zenuwstelsel en het somatische zenuwstelsel.864. De twee hoofdzenuwstelsels in ons lichaam zijn het motorisch en endocrien systeem.875. Het zenuwstelsel in het lichaam wordt met name onderverdeeld in het interne en externe zenuwstelsel.886. Het zenuwstelsel in het menselijk lichaam wordt meestal onderverdeeld in het oppervlakkige en diepe zenuwstelsel.897. Het zenuwstelsel wordt vaak onderverdeeld in het methische en het hermethische zenuwstelsel.908. De hoofdindeling van het zenuwstelsel is het voorste en het achterste zenuwstelsel."""91UserPrompt33 = r"""Studieonderwerp: Klantprofielen en marktsegmentatie92Vraag: Bij het opstellen van een klantprofiel, welke soort informatie nemen we daar voornamelijk in mee?93Juiste antwoord: Leeftijd, geslacht, en woonplaats"""94AssistantPrompt33 = r"""Misvattingen:951. In een klantprofiel worden vooral aankoop- en betalingsgeschiedenis van de klant in detail opgenomen.962. De afkomst van de klant is onmisbaar bij het opstellen van een klantprofiel.973. Wanneer we een klantprofiel samenstellen, leggen we de meeste aandacht op hun onderwijsniveau.984. Een klantprofiel wordt vooral opgesteld op basis van de politieke voorkeuren van de klant.995. Het persoonlijke inkomen van de klant is één van de belangrijkste factoren bij het vormen van een klantprofiel.1006. De religieuze overtuigingen van een klant zijn het belangrijkst bij het maken van een klantprofiel.1017. Wanneer we een klantprofiel opstellen, geven we vooral voorrang aan de gezondheidsstatus van de klant.1028. Bij het opstellen van een klantprofiel is de voornaamste informatie de carrière/beroep van de klant.1039. De militaire status is onmisbaar bij het opstellen van een klantprofiel."""104 105 106 107# Define the messages for stepFour108SystemPrompt41 = r"""Je bent een breed-geschoolde professor. Op basis van een vraag, antwoord en een lijstje met misvattingen genereer je de meest geloofwaardige, doch incorrecte, afleiders voor een meerkeuzevraag.109De afleiders moeten eenzelfde lengte, grammaticale structuur en taalniveau hebben als het juiste antwoord.110De afleiders moeten geloofwaardig klinken voor iemand die weinig over het onderwerp weet, maar daadwerkelijk volledig onjuist zijn. Ze mogen de vraag op geen enkele manier correct beantwoorden. Zorg dat zij dus het foutieve aspect van de misvatting waarop ze zijn gebaseerd behouden, op een subtiele manier."""111UserPrompt41 = r"""Je bent een expert op het gebied van 'Klantprofielen en marktsegmentatie'. 112Vraag: Welke soort informatie nemen we voornamelijk mee in het opstellen van een klantprofiel? 113Juiste antwoord: Leeftijd, geslacht, en woonplaats 114 115Misvattingen: 1161. In een klantprofiel worden vooral aankoop- en betalingsgeschiedenis van de klant in detail opgenomen.1172. De afkomst van de klant is onmisbaar bij het opstellen van een klantprofiel.1183. Wanneer we een klantprofiel samenstellen, leggen we de meeste aandacht op hun onderwijsniveau.1194. Een klantprofiel wordt vooral opgesteld op basis van de politieke voorkeuren van de klant.1205. Het inkomen van de klant is één van de belangrijkste factoren bij het vormen van een klantprofiel.1216. De religieuze overtuigingen van een klant zijn het belangrijkst bij het maken van een klantprofiel.1227. Wanneer we een klantprofiel opstellen, geven we vooral voorrang aan de gezondheidsstatus van de klant.1238. Bij het opstellen van een klantprofiel is de voornaamste informatie de carrière of het beroep van de klant.1249. De militaire status is onmisbaar bij het opstellen van een klantprofiel. """125AssistantPrompt41 = r"""Vraag: 126Welke soort informatie nemen we voornamelijk mee in het opstellen van een klantprofiel?127 128Juiste antwoord:129Leeftijd, geslacht, en woonplaats130 131Afleiders: 132Aankoop- en betaalgeschiedenis133Opleidingsniveau en politieke voorkeuren134Afkomst, religie, en gezondheidstatus135Informatie over carrière en beroep136 137 138"""139UserPrompt42 = r"""Je bent een expert op het gebied van het zenuwstelsel. 140Vraag: Tot welk zenuwstelsel behoort het ruggenmerg?141Juiste antwoord: Het centrale zenuwstelsel142 143Misvattingen:1441. Het ruggenmerg behoort tot het perifere zenuwstelsel.1452. Het motorische zenuwstelsel is waar het ruggenmerg bijhoort.1463. Het ruggenmerg behoort tot het parasympathisch zenuwstelsel.1474. Het ruggenmerg behoort tot het quadratische zenuwstelsel.1485. Het ruggenmerg behoort tot het craniale zenuwstelsel.149"""150AssistantPrompt42 = r"""Vraag: 151Tot welk zenuwstelsel behoort het ruggenmerg? 152 153Juiste antwoord: 154Het centrale zenuwstelsel155 156Afleiders: 157Het perifere zenuwstelsel 158Het motorische zenuwstelsel159Het parasympathisch zenuwstelsel160Het quadratische zenuwstelsel"""161 162## Define the messages for stepFive163#UserPrompt41 =  r""""""164#AssistantPrompt41 = r""""""165#UserPrompt42 = r""""""166#AssistantPrompt42 = r""""""167#UserPrompt43 = r""""""168#AssistantPrompt43 = r""""""169 170# Function to make API call171def api_call(messages, temperature=0.9, model="gpt-4"):172    return openai.ChatCompletion.create( 173        messages=messages,174        temperature=temperature,175        model=model176    ).choices[0].message.content177 178# Function to be called by Gradio interface179def chatbot(input):180    # Check if input is empty181    if not input:182        return manual183    # Check if input text contains '[CDATA'184    if "[CDATA" in input:185    # Step 1: User input and first API call ~5secs186        stepOne = [187            {"role": "system", "content": "You distill a takeaway out of an exercise's question and answer. Mark the answer part in triple quotes '''. Don't do anything else."},188            {"role": "user", "content": UserPrompt1},189            {"role": "assistant", "content": AssistantPrompt1},190            {"role": "user", "content": UserPrompt2},191            {"role": "assistant", "content": AssistantPrompt2},192            {"role": "user", "content": UserPrompt3},193            {"role": "assistant", "content": AssistantPrompt3},194            {"role": "user", "content": input}195        ]196        Takeaway = api_call(stepOne, 0.4)197        strippedTakeaway = Takeaway.replace("'''", '')198    else:199# Skip stepOne and set 'Takeaway' to input200        strippedTakeaway = input.replace("'''", '')201        Takeaway = input202    # Step 2: second API call with first call's output as input ~2secs203    stepTwo = [204        {"role": "system", "content": "Je bent onderwijskundige. Genereer 1 vraag waarmee je de kennis van de student toetst over een specifiek stukje informatie (kennisonderdeel)."},205        {"role": "user", "content": UserPrompt21},206        {"role": "assistant", "content": AssistantPrompt21},207        {"role": "user", "content": UserPrompt22},208        {"role": "assistant", "content": AssistantPrompt22},209        {"role": "user", "content": "Kennisonderdeel: " + Takeaway}210    ]211    QandA = api_call(stepTwo, 0.5, "gpt-3.5-turbo")212 213    # Split the QandA string into question and answer parts214    lines = QandA.split('\n')215    # Isolate just the question and answer 216    question = lines[0].split('Vraag: ')[1].strip()217    answer = lines[1].split('Juiste antwoord: ')[1].strip().rstrip(".")218 219    # Step 3: next API call with previous call's output as input ~21secs220    stepThree = [221        {"role": "system", "content": SystemPrompt31},222        {"role": "user", "content": UserPrompt31},223        {"role": "assistant", "content": AssistantPrompt31},224        {"role": "user", "content": UserPrompt32},225        {"role": "assistant", "content": AssistantPrompt32},226        {"role": "user", "content": QandA}227    ]228    misvattingen = api_call(stepThree)229    230#Step 4: ALL elements next API call with previous call's output as input ~23secs231    stepFour = [232        {"role": "system", "content": SystemPrompt41},233        {"role": "user", "content": UserPrompt41},234        {"role": "assistant", "content": AssistantPrompt41},235        {"role": "user", "content": UserPrompt42},236        {"role": "assistant", "content": AssistantPrompt42},237        {"role": "user", "content": "Je bent medisch expert.\n" + QandA + "\n\n" + misvattingen}238    ]239    BOTA_mc_elements = api_call(stepFour, 0.7)240 241    # Split the BOTA_mc_elements string by lines242    lines = BOTA_mc_elements.split('\n')243 244    # Find the index where "Afleiders:" appears245    distractors_index = -1  # Initialize to -1 as a sentinel value246    for i, line in enumerate(lines):247        if line.strip() == "Afleiders:":248            distractors_index = i249            break250 251    if distractors_index != -1:252       # Extract the afleiders into the distractors list and remove any trailing periods253        distractors = [line.rstrip('.').strip() for line in lines[distractors_index + 1:] if line.strip()]254    else:255        # Handle the case where "Afleiders:" is not found256        distractors = []257        distractors.append("Geen afleiders gevonden. Herlaad de pagina, klik zonder input op 'Submit' voor instructies, en probeer opnieuw. Gaat het een tweede keer mis? Stuur Ben ten Berge een berichtje met je input.")258        distractors.append("Geen afleiders gevonden. Herlaad de pagina, klik zonder input op 'Submit' voor instructies, en probeer opnieuw. Gaat het een tweede keer mis? Stuur Ben ten Berge een berichtje met je input.")259 260    # Generate the two versions of 'Beide bovenstaande' type261    exercise_1 = f"Vraag:\n{question}\n\n{answer}   ✔\n{distractors[0]}\n{distractors[1]}\n{distractors[2]}\n\n\n\n---------------------\nBonus-afleider:\n{distractors[3]}\n\n---------------------\nOf maak er een 'Beide bovenstaande'-vraag van:\nBeide bovenstaande\nGeen van bovenstaande\n\nExtra info:\n{Takeaway}"262    exercise_2 = f"Vraag:\n{question}\n\n{distractors[0]}\n{answer}   ✔\n{distractors[1]}\n{distractors[2]}\n\n\n\n---------------------\nBonus-afleider:\n{distractors[3]}\n\n---------------------\nOf maak er een 'Beide bovenstaande'-vraag van:\nBeide bovenstaande\nGeen van bovenstaande\n\nExtra info:\n{Takeaway}"263    exercise_3 = f"Vraag:\n{question}\n\n{distractors[0]}\n{distractors[1]}\n{answer}   ✔\n{distractors[2]}\n\n\n\n---------------------\nBonus-afleider:\n{distractors[3]}\n\n---------------------\nOf maak er een 'Beide bovenstaande'-vraag van:\nBeide bovenstaande\nGeen van bovenstaande\n\nExtra info:\n{Takeaway}"264    exercise_4 = f"Vraag:\n{question}\n\n{distractors[0]}\n{distractors[1]}\n{distractors[2]}\n{answer}   ✔\n\n\n\n---------------------\nBonus-afleider:\n{distractors[3]}\n\n---------------------\nOf maak er een 'Beide bovenstaande'-vraag van:\nBeide bovenstaande\nGeen van bovenstaande\n\nExtra info:\n{Takeaway}"265    266    # Define the probabilities267    probabilities = [0.25, 0.25, 0.25, 0.25]  # 25% each (dit kan ongetwijfeld makkelijker en beter.. #quickfix)268    # Randomly choose between OneTrue and NoneTrue based on the probabilities269    random_version = random.choices([exercise_1, exercise_2, exercise_3, exercise_4], weights=probabilities, k=1)[0]270 271    return random_version272   273 274inputs = gr.Textbox(lines=7, label="Input")275outputs = gr.Textbox(label="Output")276 277# Create the Gradio interface with HTML-formatted output278iface = gr.Interface(279    fn=chatbot,280    inputs=inputs,281    outputs=outputs,282    title="Leerdoel naar standaard MC-opgave [v1]",283    description="Voer een leerdoel in en druk op 'Submit'.",284    theme="compact",285    port=7862286)287 288iface.launch(share=True)