Code viewer for World: Dating Profile Generator

// Cloned by Anand on 26 Nov 2023 from World "Chat with GPT model" by Starter user 
// Please leave this clone trail here.
 


//Practical 2 : 
//Use an AI API to achieve a function: 
//2 worlds - Hello world to introduce the API and one where API is used heavily . 
//Pick top 2 news article and TL;DR those. 


const openaiURL = "https://api.openai.com/v1/chat/completions";           // can POST to this 3rd party URL
const openai_moderations_URL = "https://api.openai.com/v1/moderations";
const themodel = "gpt-3.5-turbo";       // the OpenAI model we are going to talk to 
//const apikey = "";// 01983019283; //copy GPT API Key
const prompts = []; 
var apikey = ""; 

prompts[0]   = "What makes a relationship great is...";
prompts[1]   = "Two truths and a lie ...";
prompts[2]   = "I'm hoping you...";
prompts[3]   = "If I could eat only one meal for the rest of my life it would be ...";
prompts[4]   = "My third-grade teacher described me as ...";
prompts[5]   = "I'm a great +1 because ...";
prompts[6]   = "I promise I won't judge you if ...";
prompts[7]   = "My zombie apocalypse plan is ..." ;
prompts[8]   = "A pro and con of dating me ...";
prompts[9]   = "I will never shut up about ...";
prompts[10]  = "My personal hell is ...";
prompts[11]  = "A world would be a better place with more ...";
prompts[12]  = "I'm still not over ...";
prompts[13]  = "Quickest way to my heart ...";
prompts[14]  = "After work you can find me ...";
prompts[15]  = "My current obsession ...";
prompts[16]  = "If I could have one superpower it'd be ...";
prompts[17]  = "Favorite quality in a person ...";

// default API key and prompt:

var topic = "hello";
var final_str; 
var content_moderation_failed = 0;
var content_moderation_reasons = []; 
var gpt_temperature = 0.2; 
 
// default body is margin 0 and padding 0 
// give it more whitespace:

  $('body').css( "margin", "100px" );
  $('body').css( "padding", "100px" );
  $('body').css( "background-color", "red");
  $('body').css( "box-sizing", "border-box" );
  $('body').css( "list-style", "none" );
  $('InfoDiv').css ("font-family", "Arial");

document.write ( `
<h1> Your AI wingman </h1>


<div id=enterkey>
Enter API key: 
	<input    style='width:25vw;'    maxlength='2000'   NAME="apikey"    id="apikey"       VALUE='' >  
	<button onclick='setkey();'  class=ab-normbutton >Set API key</button>
</div>



<div class="InfoDiv" style="width:60vw; background-color:pink;  border: 1px solid black; margin:20; padding: 20px;">

<h3> Answer a few questions and get an AI-generated dating app profile </h3>

Who are you ?: 
<select id="Gender", name = "Gender" required>
  <option value="Man" selected>Man</option>
  <option value="Woman">Woman</option>
  <option value="Non-Binary">Non-Binary</option>
</select>
<hr>

How old are you : 
<input  type=number  style='width:5vw;'    maxlength='2'   NAME="Age"    id="EnterAge"  required>  
<hr>

Pick some interests <br>

<input class="interestCheckbox" type="checkbox" id="interest1" name="Biking" >
<label for="interest1"> Biking </label>

<input class="interestCheckbox" type="checkbox" id="interest2" name="Hiking" >
<label for="interest2"> Hiking </label>

<input class="interestCheckbox" type="checkbox" id="interest3" name="Road Trips" >
<label for="interest3"> Road Trips </label>

<input class="interestCheckbox" type="checkbox" id="interest4" name="Bouldering" >
<label for="interest4"> Bouldering </label>

<input class="interestCheckbox" type="checkbox" id="interest5" name="Skiing" >
<label for="interest5"> Skiing </label>

<input class="interestCheckbox" type="checkbox" id="interest6" name="wine tasting" >
<label for="interest6"> Wine tasting </label>

<input class="interestCheckbox" type="checkbox" id="interest7" name="dancing" >
<label for="interest7"> Dancing </label>

<input class="interestCheckbox" type="checkbox" id="interest8" name="watching movies" >
<label for="interest8"> Watching Movies </label><br>

<pre>

</pre>

Want to add your own ? (90's sitcoms, cafe-hopping ...) : 
<input  type=text  style='width:50vw;'    maxlength='2000'   NAME="Interests" value="sea swimming, bowling, kayaking"    id="UserDefInterests">  <br>


<hr>

Which personality trait do you lean towards ?: 
<select id="Personality">
  <option label="Introvert">Introvert</option>
  <option label="Extrovert">Extrovert</option>
</select>
<hr>

What are you looking for? 
<select id="RelationGoal">
  <option label="Something Casual">Something Casual</option>
  <option label="A Long term partner">Long term partner</option>
  <option label="Not sure yet">Not sure yet</option>
</select>

<hr>

What characteristics are you looking for in your partner ? (Humorous, sporty, nerdy ...) : 
<input  type=text  style='width:50vw;'    maxlength='2000'   NAME="characteristics"  value="funny, kind"  id="characteristics">  <br>

<hr>


<h3> Can you put some basic details apart from the options selected above (the more detailed the better) </h3>

<input  type=text  style='width:50vw;'    maxlength='2000'   NAME="basicinfo"  value="I'm an easy going person who loves to be outdoors and explore new places"  id="basicinfo">  <br>

<hr>

Which Dating App would you be using ? 
<select id="App_ID">
  <option label="Bumble">Bumble</option>
  <option label="Hinge">Hinge</option>
  <option label="Tinder">Tinder</option>
</select>

<hr>
Qurkiness level : A quirky response may be very random - you might find some funny bits and pieces (Keep it below 65 - explained in report). 

<div class="slidecontainer">
  <input type="range" min="0" max="100" value="25" class="slider" id="myRange">
  <p>Quirkiness Index: <span id="demo"></span></p>
</div>
<hr>


<br>
<hr>
<button onclick='setInterests();'  class=ab-normbutton >Submit</button>
</div>

</div>

<div style="width:60vw; background-color:#ffffff;  border: 1px solid black; margin:20; padding: 20px;">
<div id=content_moderation > </div>
</div>


<div style="width:60vw; background-color:#ffffcc;  border: 1px solid black; margin:20; padding: 20px;">
<h3> Response:  </h3>
<div id=them > </div>
</div>
 
 
 
<p> <i> Caution : :: .<br> 
The AI model has generated this based on an idea it has about you - it may or may not be accurate !. 
If you end up going on a date - disclose the information ! Gets you a topic to talk on !! 
</i> </p>

<pre>

</pre>


` );



function setInterests() {
    
    
    
    my_gender   = jQuery("select#Gender").val();
    my_age      = jQuery("input#EnterAge").val();
    
    final_str = `My information : Age: ${my_age} Gender: ${my_gender}. Hobbies/Interests:`;
    
    var my_interests = [];
    var checkedValue = null; 
    var inputElements = document.getElementsByClassName('interestCheckbox');
    for(var i=0; inputElements[i]; ++i){
        var j = 0; 
        if(inputElements[i].checked){
            my_interests[j] = inputElements[i].name; 
            final_str = final_str.concat(my_interests[j], ", ");
            console.log("Interests : " + my_interests[j])
            j = j+1; 
        }
    }
    if(my_interests.length === 0) {
        
    }
    
    var my_add_interests            = jQuery("#UserDefInterests").val()
    var my_personality              = jQuery("select#Personality").val();
    var my_relation_goal            = jQuery("select#RelationGoal").val();
    var my_partner_characteristics  = jQuery("#characteristics").val()
    var my_basicinfo                = jQuery("#basicinfo").val()

    var user_inputs = [];
    user_inputs[0]  = my_add_interests; 
    user_inputs[1]  = my_partner_characteristics;
    user_inputs[2]  = my_basicinfo;
    
    

    //Check moderations on content provided by users:
    //Need to do this on each smaller string because GPT's moderation failed to detect foul phrases on the final string which is passed. 
    for(var i=0; i<user_inputs.length ; i++) {
        
        check_content_moderation(user_inputs[i]);
        console.log("done with loop");
    }
    
    if(content_moderation_failed == 1) {
        
        var info = "<font color=red><b> Content moderation failed - your inputs possibly contain language indicating : ";
        for(var i=0; i<content_moderation_reasons.length; i++) {
            info = info.concat(content_moderation_reasons[i], " ");
        }
        info = info.concat("</b></font>")
        console.log("content moderation failed, info = " + info);
        $("#content_moderation").html ( info );
        content_moderation_failed = 0; 
        
    } else {
        
    //Don't bother continuing if content moderation failed 
        if(my_add_interests) {
            final_str = final_str.concat(" ", my_add_interests)
        }
        
        final_str.concat(" Personality leans towards: ", my_personality);
        
        if(my_relation_goal){
            if(my_relation_goal == "Not sure yet"){
                //Keep it a mystery
            } else {
                final_str = final_str.concat(" Looking for: ", my_relation_goal)
            }
        }
        if(my_partner_characteristics) {
            final_str = final_str.concat(" I get along really well with someone who has the following traits: ", my_partner_characteristics);
        }
        if(my_basicinfo) {
            final_str = final_str.concat(" Some more information: ", my_basicinfo); 
        }
    
        console.log(final_str);
        $("#content_moderation").html ( " " );
        sendchat();
    }
    
}


function setkey()          
{
	apikey =  jQuery("input#apikey").val();
	apikey = apikey.trim();
	$("#enterkey").html ( "<b> API key has been set. </b>" );
}



// Enter will also send chat:

	//document.getElementById('newstopic').onkeydown   = function(event) 	{ if (event.keyCode == 13)  sendchat(); };
    var slider = document.getElementById("myRange");
    var m_output = document.getElementById("demo");
    m_output.innerHTML = slider.value;
    
    slider.oninput = function() {
        gpt_temperature = mapRange(this.value, 0, 100, 0.1, 1.8);
        m_output.innerHTML = this.value;
        console.log("gpt-temp = " + gpt_temperature);
    }


    function mapRange(value, inMin, inMax, outMin, outMax) {
        return ((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
    }

// --- Send my line of text ----------------------------------------------------------------

function sendchat()
{


    var dating_app            = jQuery("select#App_ID").val();
    
    //var shuffledprompts = shuffle(prompts); 
    let gpt_query = `${final_str}. \n Can you generate a funny and punchy bio best suited for the dating app ${dating_app}. which you can generate using my information provided above ?`;
    //if(dating_app == "Bumble" || dating_app == "Hinge") {
    if(dating_app.match(/Bumble|Hinge/)) {    
        //Tinder does not require an app as of now
        gpt_query = gpt_query.concat(" Also pick some prompts which ", dating_app  ," provides which can be best answered by the information provided, add some twist to the prompts but keep it all real");
    }
    for(var i =1 ; i < prompts.length + 1; i++) {
        if(prompts[i]){
            //gpt_query = gpt_query.concat(`${i}. `, prompts[i], " ");
        }
    }    
    console.log(gpt_query);
    
    
    var thedata = {
     "model": themodel,
     "temperature": gpt_temperature,
     "messages": [{
         "role": "user", 
         "content": gpt_query
        }] 
   };
   
// then as string representing that JSON:
var thedatastring = JSON.stringify ( thedata ); 
  
 
  
$.ajaxSetup({
   headers:
   {
        "Content-Type": "application/json",
        "Authorization": "Bearer " + apikey  
   }
});

console.log(thedatastring);
 //First check for moderation of input data - make sure there's no offensive things in there 


 $.ajax({
    type: "POST",
    url: openaiURL,
    data: thedatastring,
   dataType: "json",
    success: function ( d, rc ) { successfn ( d, rc ); },
      error: function()         { errorfn (); }
 });
 
 
 //Send in the second token to actually generate a prompt. 
}


 
 // global variable to examine return data in console 
 var a;
 
function check_content_moderation (data) {
     

     
     var moderation_data = {
        "input": data
    } ;
    
    var moderation_str = JSON.stringify(moderation_data);
    
    console.log("moderation input = : " + moderation_str);
    
    
    $.ajaxSetup({
   headers:
   {
        "Content-Type": "application/json",
        "Authorization": "Bearer " + apikey  
   }
});
    
    $.ajax({
    type: "POST",
    url: openai_moderations_URL,
    async: false,
    data: moderation_str,
    dataType: "json",
    success: function ( d, rc ) { mod_successfn ( d, rc ); },
    error: function()           { errorfn (); }
    
});
    
   // _callback();
}
 
 function mod_successfn(data, rc) {
     a = data; 
     console.log("moderation success : " + a["results"][0].flagged); 
     
     if(a["results"][0].flagged === true ) {
         content_moderation_failed = 1; 
         var obj = a["results"][0].categories;
         
         for (var key in obj) {
             if(obj[key] === true) {
                 content_moderation_reasons.push(key);
             }
             console.log("moderation content : " + key + " : " + obj[key] + "content_mod = " + content_moderation_failed);
         }
     }
     
 }
 
 function mod_errorfn(data, rc) {

     console.log("something went wrong with moderation API "); 
     if ( apikey == "" )    $("#them").html ( "<font color=red><b> Enter API key to be able to chat. </b></font>" );
     else                   $("#them").html ( "<font color=red><b> Unknown error. </b></font>" ); 
     
 }
 
 function successfn ( data, rc )
 {
     a = data;
     var answer = a["choices"][0].message.content;
     $("#them").html ( answer );
 }
 
 function errorfn()
 {
     if ( apikey == "" )    $("#them").html ( "<font color=red><b> Enter API key to be able to chat. </b></font>" );
     else                   $("#them").html ( "<font color=red><b> Unknown error. </b></font>" ); 
 }