// Cloned by Antoine Podvin on 2 Dec 2023 from World "Chat with GPT model" by Starter user
// Please leave this clone trail here.
// talk to OpenAI GPT model (ChatGPT)
// adapted from:
// https://platform.openai.com/docs/api-reference/making-requests
const openaiURL = "https://api.openai.com/v1/chat/completions"; // can POST to this 3rd party URL
const themodel = "gpt-3.5-turbo"; // the OpenAI model we are going to talk to
// default API key and prompt:
var apikey = "";
var theprompt = "Hello, World!";
// default body is margin 0 and padding 0
// give it more whitespace:
$('body').css( "margin", "20px" );
$('body').css( "padding", "20px" );
var threeJsScript = document.createElement('script');
threeJsScript.setAttribute('src','https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js');
document.head.appendChild(threeJsScript);
document.write ( `
<h1> CA318 - AI APIs - Practical </h1>
<h3> Made by Antoine Podvin (23101221 - ECSAO) and William Mallevays (23101221 - ECSAO). </h3>
<br>
Running World:
<a href='https://ancientbrain.com/world.php?world=5162534048'>AI APIs - Practical (Antoine Podvin & William Mallevays)</a>.
<br>
Chat with
<A HREF="https://platform.openai.com/docs/models/overview">GPT 3.5</A>
using the
<A HREF="https://en.wikipedia.org/wiki/OpenAI">OpenAI </A> API.
<br>
This is the model
<A HREF="https://en.wikipedia.org/wiki/ChatGPT">ChatGPT</A> uses.
<pre>
</pre>
<h3> Enter API key </h3>
The crucial thing is you need an "API key" to talk to OpenAI. <br>
Register for free and get your API key
<a href='https://platform.openai.com/account/api-keys'>here</a>.
<br>
You enter your API key below and then chat away.
Then communications to OpenAI come from your IP address using your API key.
<br>
This World will never store your API key.
You can view the <a href='https://ancientbrain.com/viewjs.php?world=5162534048'> source code</a> to see that is true!
<p>
<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>
<pre>
</pre>
<div style="width:60vw; background-color:white; border: 1px solid black; margin:20; padding: 20px;">
<h3> Choose the "temperature" of the reply </h3>
<p> (The temperature is used to control the randomness of the output, the default value is 0.7) </p>
<div class="slidecontainer" style="display: flex; flex-direction: row">
<p style="margin-right: 1rem;">Temperature: <span id="sliderValue"></span></p>
<input type="range" min="0" max="20" value="7" class="slider" id="slider">
</div>
<h3> Enter a "prompt" </h3>
<INPUT style="width:50vw;" id=me value="Hello, World!" >
<button id="sendButton" onclick="sendchat();" class=ab-normbutton > Send </button>
<div style="margin-top: 10px;">
<input id="generateThreeJS" type="checkbox"></input>
<label for="generateThreeJS"> Generate answer in a Three.js 3D scene </label>
</div>
</div>
<div style="width:60vw; overflow: auto; background-color:#ffffcc; border: 1px solid black; margin:20; padding: 20px;">
<h3> GPT replies </h3>
<p style="font-style: italic;"> (Answers generated in a Three.js 3D scene will be displayed one after the other) </p>
<p style="display: none" id="loadingDots">Loading GPT reply.</p>
<div id="sceneContainer" style="display: none; height: 800px; width: 800px; gap: 30px;"></div>
<div id=them > </div>
</div>
<p> <i> Be warned that GPT replies are often completely inaccurate.<br>
All LLM systems <a href="https://www.google.com/search?q=llm+hallucination"> "hallucinate"</a>.
It is how they work. </i> </p>
<pre>
</pre>
` );
var slider = document.getElementById("slider");
var output = document.getElementById("sliderValue");
output.innerHTML = slider.value / 10;
slider.oninput = function() {
output.innerHTML = this.value / 10;
}
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('me').onkeydown = function(event) { if (event.keyCode == 13) sendchat(); };
// --- Send my line of text ----------------------------------------------------------------
function sendchat()
{
if($("#generateThreeJS").is(':checked'))
console.log("checked");
else
console.log("unchecked");
$('#loadingDots').css( "display", "block" );
if($("#generateThreeJS").is(':checked'))
theprompt = 'Generate the three.js code to draw inside a div of size 800px and 800px with the id "sceneContainer" (answer only with the code without comments), that fulfill the user prompt: ' + $("#me").val() + ' (camera must be wide so all elements must be visible, not touching each other and be animated)';
else
theprompt = $("#me").val();
// construct request as JSON
// "Lowering temperature means it will take fewer risks, and completions will be more accurate and deterministic. Increasing temperature will result in more diverse completions."
var thedata = {
"model": themodel,
"temperature": slider.value / 10,
"messages": [{
"role": "user",
"content": theprompt
}]
};
// then as string representing that JSON:
var thedatastring = JSON.stringify ( thedata );
// HTTP headers must be set up with API key:
$.ajaxSetup({
headers:
{
"Content-Type": "application/json",
"Authorization": "Bearer " + apikey
}
});
// POST to 3rd party URL:
$.ajax({
type: "POST",
url: openaiURL,
data: thedatastring,
dataType: "json",
success: function ( d, rc ) { successfn ( d, rc ); },
error: function() { errorfn (); }
});
}
setInterval(function(){
const value = $("#loadingDots").html();
if (value == "Loading GPT reply.")
$("#loadingDots").html("Loading GPT reply..")
else if (value == "Loading GPT reply..")
$("#loadingDots").html("Loading GPT reply...")
else
$("#loadingDots").html("Loading GPT reply.")
}, 500);
// global variable to examine return data in console
var a;
function successfn ( data, rc )
{
$('#loadingDots').css( "display", "none" );
a = data;
var answer = a["choices"][0].message.content;
if($("#generateThreeJS").is(':checked')) {
$('#sceneContainer').css( "display", "block" );
$('#them').css( "display", "none" );
console.log(answer);
answer = answer.replace("```javascript", "");
answer = answer.replace("```", "");
eval(answer);
} else {
$('#sceneContainer').css( "display", "none" );
$('#them').css( "display", "block" );
$("#them").html ( answer );
}
}
function errorfn()
{
$('#loadingDots').css( "display", "none" );
$('#sceneContainer').css( "display", "none" );
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>" );
$('#them').css( "display", "block" );
}