Skip to content

Commit 2aea88c

Browse files
Dall-E + GTP web apps
1 parent af0b733 commit 2aea88c

6 files changed

Lines changed: 386 additions & 0 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
* {
2+
/* border: 1px solid coral; */
3+
font-family: 'Courier New', Courier, monospace;
4+
font-size: 18px;
5+
}
6+
7+
.target-text {
8+
font-weight: 900;
9+
}
10+
11+
fieldset {
12+
margin-bottom: 8px;
13+
}

Misc/Dall-E/web-dalle/index.html

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<!DOCTYPE html>
2+
3+
<html>
4+
<header>
5+
<title>Dall-E Webapp</title>
6+
7+
<link rel="stylesheet" type="text/css" href="css/styles.css">
8+
</header>
9+
10+
<body>
11+
<p>A custom OpenAI webapp for Dall-E</p>
12+
13+
<fieldset>
14+
<legend>Setup</legend>
15+
<div>
16+
Please enter your <a href="https://www.youtube.com/watch?v=DFmmiYlbgX0&list=PLx3k0RGeXZ_zs3az0Z2BnpTIPH2lxQfFX&index=4" target="_blank">OpenAI API Key</a>: <input id="api-key" value="YOUR-API-KEY-HERE">
17+
</div>
18+
</fieldset>
19+
20+
<fieldset>
21+
<legend>Request parameters</legend>
22+
<div>
23+
<textarea id="text-prompt" rows="4" cols="52">An isometric view of a miniature city, tilt shift, bokeh, voxel, vray render, high detail</textarea>
24+
</div>
25+
26+
<div>
27+
Image count (1-4): <input id="image-count" value="1">
28+
</div>
29+
30+
<div>
31+
Image size:
32+
</div>
33+
34+
<div>
35+
<input type="radio" id="radio-256" name="image-size" value="256" checked>
36+
<label for="256">256</label>
37+
</div>
38+
<div>
39+
<input type="radio" id="radio-512" name="image-size" value="512">
40+
<label for="512">512</label>
41+
</div>
42+
<div>
43+
<input type="radio" id="radio-1024" name="image-size" value="1024">
44+
<label for="1024">1024</label>
45+
</div>
46+
47+
<div>
48+
<button id="button-request">Request</button>
49+
</div>
50+
</fieldset>
51+
52+
<fieldset>
53+
<legend>Request Status</legend>
54+
<div>
55+
<p id="request-status">No request performed yet</p>
56+
</div>
57+
</fieldset>
58+
59+
<fieldset>
60+
<legend>Images</legend>
61+
62+
<!-- Response images will be added here -->
63+
<div id="image-container"></div>
64+
65+
</fieldset>
66+
67+
<script type="text/javascript" src="js/script.js"></script>
68+
</body>
69+
</html>

Misc/Dall-E/web-dalle/js/script.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
2+
const dalleEndpoint = 'https://api.openai.com/v1/images/generations';
3+
const reqButton = document.getElementById('button-request');
4+
const imgContainer = document.getElementById('image-container');
5+
const reqStatus = document.getElementById('request-status');
6+
7+
reqButton.onclick = function() {
8+
reqStatus.innerHTML = "Performing request...";
9+
10+
const key = document.getElementById('api-key').value;
11+
const prompt = document.getElementById('text-prompt').value;
12+
const count = Number(document.getElementById('image-count').value);
13+
const radios = document.getElementsByName('image-size');
14+
let size;
15+
for (let i = 0; i < radios.length; i++)
16+
{
17+
if (radios[i].checked)
18+
{
19+
size = Number(radios[i].value);
20+
break;
21+
}
22+
}
23+
24+
const reqBody = {
25+
prompt: prompt,
26+
n: count,
27+
size: size + "x" + size,
28+
response_format: "url"
29+
}
30+
// console.log(reqBody);
31+
32+
const reqParams = {
33+
method: 'POST',
34+
headers: {
35+
'Content-Type': 'application/json',
36+
'Authorization': `Bearer ${key}`,
37+
},
38+
body: JSON.stringify(reqBody)
39+
}
40+
41+
fetch(dalleEndpoint, reqParams)
42+
.then(res => res.json())
43+
// .then(json => console.log(json))
44+
.then(addImages)
45+
.catch(error => reqStatus.innerHTML = error);
46+
47+
}
48+
49+
function addImages(jsonData)
50+
{
51+
if (jsonData.error)
52+
{
53+
reqStatus.innerHTML = 'ERROR: ' + jsonData.error.message;
54+
return;
55+
}
56+
57+
reqStatus.innerHTML = "Successfully retrieved " + jsonData.data.length + " images!";
58+
59+
for (let i = 0; i < jsonData.data.length; i++)
60+
{
61+
const imgURL = jsonData.data[i].url;
62+
const imgNode = document.createElement('img');
63+
imgNode.src = imgURL;
64+
65+
imgContainer.prepend(imgNode);
66+
}
67+
}

Misc/Dall-E/web-gpt/css/styles.css

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
* {
2+
/* border: 1px solid coral; */
3+
font-family: 'Courier New', Courier, monospace;
4+
font-size: 18px;
5+
}
6+
7+
.target-text {
8+
font-weight: 900;
9+
}
10+
11+
fieldset {
12+
margin-bottom: 8px;
13+
}
14+
15+
.question {
16+
background-color: darkslategray;
17+
color: azure;
18+
}
19+
20+
.answer {
21+
background-color: gainsboro;
22+
}
23+
24+
.reason {
25+
/* background-color: azure; */
26+
margin-bottom: 36px;
27+
}
28+
29+
.reason > p {
30+
font-size: 10px;
31+
}

Misc/Dall-E/web-gpt/index.html

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<title>Hello GPT</title>
6+
7+
<link rel="stylesheet" type="text/css" href="css/styles.css">
8+
</head>
9+
10+
<body>
11+
<p>A sample webpage to learn how to query the Text Completion API from a front end application.</p>
12+
13+
<fieldset>
14+
<legend>Setup</legend>
15+
16+
<div id="controls">
17+
Please enter your OpenAI <a href="https://youtu.be/DFmmiYlbgX0" target="_blank">API key</a>:
18+
<input id="api-key" value="YOUR-API-KEY-HERE">
19+
</div>
20+
</fieldset>
21+
22+
<fieldset>
23+
<legend>Prompt</legend>
24+
25+
<textarea id="text-prompt" rows="4" cols="52">Tell me the story of an invisible city full of dreamful architects</textarea>
26+
27+
<div>Text Model:</div>
28+
<div>
29+
<input type="radio" id="model-davinci" name="text-model" value="text-davinci-003" checked>
30+
<label for="text-davinci-003">Davinci (better)</label>
31+
</div>
32+
<div>
33+
<input type="radio" id="model-curie" name="text-model" value="text-curie-001">
34+
<label for="text-curie-001">Curie</label>
35+
</div>
36+
<div>
37+
<input type="radio" id="model-babbage" name="text-model" value="text-babbage-001">
38+
<label for="text-babbage-001">Babbage</label>
39+
</div>
40+
<div>
41+
<input type="radio" id="model-ada" name="text-model" value="text-ada-001">
42+
<label for="text-ada-001">Ada (faster)</label>
43+
</div>
44+
45+
<div>
46+
<div>Max. tokens (similar to words): <input id="token-count" value="256"></div>
47+
</div>
48+
49+
<div>
50+
<div>Temperature (0-1): <input id="temperature" value="0.1"></div>
51+
</div>
52+
53+
<div>
54+
<button id="button-request">Request</button>
55+
</div>
56+
57+
</fieldset>
58+
59+
<fieldset>
60+
<legend>Request Status</legend>
61+
<div>
62+
<p id="request-status">No request performed yet</p>
63+
</div>
64+
</fieldset>
65+
66+
<fieldset>
67+
<legend>Text Completions</legend>
68+
69+
<!-- Received text will be added here -->
70+
<div id="text-container"></div>
71+
</fieldset>
72+
73+
<!-- Load the main script at the end of the page, when all the DOM elements are already present -->
74+
<script type="text/javascript" src="js/script.js"></script>
75+
</body>
76+
77+
</html>

Misc/Dall-E/web-gpt/js/script.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// We can define here the behavior for the elements on the website...
2+
3+
// URL for POST requests
4+
const gptEndpoint = 'https://api.openai.com/v1/completions';
5+
6+
// Fetch DOM elements
7+
const reqButton = document.getElementById('button-request');
8+
const reqStatus = document.getElementById('request-status');
9+
10+
// Attach click behavior to the button
11+
reqButton.onclick = function () {
12+
// Give some feedback to user
13+
reqStatus.innerHTML = "Request started...";
14+
15+
// Fetch image request data
16+
const key = document.getElementById('api-key').value;
17+
const prompt = document.getElementById('text-prompt').value;
18+
const radios = document.getElementsByName('text-model');
19+
let model;
20+
for (let i = 0; i < radios.length; i++) {
21+
if (radios[i].checked) {
22+
model = radios[i].value;
23+
break;
24+
}
25+
}
26+
const tokens = Number(document.getElementById('token-count').value);
27+
const temp = Number(document.getElementById('temperature').value);
28+
29+
// We won't do error-checking here, will leave that up to the server...
30+
31+
// Form the request body according to the API:
32+
// https://api.openai.com/v1/completions
33+
const reqBody = {
34+
model: model,
35+
prompt: prompt,
36+
max_tokens: tokens,
37+
temperature: temp,
38+
top_p: 0.5,
39+
stream: false,
40+
logprobs: null,
41+
// stop: "\n" // this was returning empty completions
42+
};
43+
44+
// Form the data for a POST request:
45+
const reqParams = {
46+
method: 'POST',
47+
headers: {
48+
'Content-Type': 'application/json',
49+
'Authorization': `Bearer ${key}`,
50+
},
51+
body: JSON.stringify(reqBody)
52+
}
53+
54+
// Use the Fetch API to do an async POST request to OpenAI:
55+
// https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
56+
fetch(gptEndpoint, reqParams)
57+
.then(res => res.json())
58+
.then(json => addText(json, prompt))
59+
.catch(error => reqStatus.innerHTML = error)
60+
}
61+
62+
63+
64+
/**
65+
* Add prompts + answers to the page.
66+
* @param {Object} jsonData The text completion API response
67+
* @param {String} prompt The original prompt that generated the text completion
68+
* @returns
69+
*/
70+
function addText(jsonData, prompt) {
71+
console.log(jsonData);
72+
73+
// Handle a possible error response from the API
74+
if (jsonData.error)
75+
{
76+
reqStatus.innerHTML = 'ERROR: ' + jsonData.error.message;
77+
return;
78+
}
79+
80+
// Parse the response object and attach a new text field to the page.
81+
const container = document.getElementById('text-container');
82+
for (let i = 0; i < jsonData.choices.length; i++)
83+
{
84+
// Prompt text box
85+
const questionDiv = document.createElement('div');
86+
questionDiv.className = "question";
87+
const questionP = document.createElement('p');
88+
questionP.innerHTML = prompt;
89+
questionDiv.appendChild(questionP);
90+
91+
// Answer text box
92+
const textData = jsonData.choices[i].text;
93+
const answerDiv = document.createElement('div');
94+
answerDiv.className = "answer";
95+
const answerP = document.createElement('p');
96+
answerP.innerHTML = textData;
97+
answerDiv.appendChild(answerP);
98+
99+
// Reason text box
100+
let reasonData;
101+
switch (jsonData.choices[i].finish_reason)
102+
{
103+
case "length":
104+
reasonData = "(Text generation stopped due to text length)"
105+
break;
106+
case "stop":
107+
reasonData = "(Model decided this length of an answer was sufficient)"
108+
break;
109+
default:
110+
reasonData = "(Text generation stopped due to unknown reasons)"
111+
break;
112+
}
113+
const reasonDiv = document.createElement('div');
114+
reasonDiv.className = "reason";
115+
const reasonP = document.createElement('p');
116+
reasonP.innerHTML = reasonData;
117+
reasonDiv.appendChild(reasonP);
118+
119+
// Prepend them at the top of the container
120+
container.prepend(
121+
questionDiv,
122+
answerDiv,
123+
reasonDiv
124+
);
125+
}
126+
127+
// Log some feedback
128+
reqStatus.innerHTML = jsonData.choices.length +' responses received for "' + prompt + '"';
129+
}

0 commit comments

Comments
 (0)